Trouble defining markup functiion
I'm trying to define a markup function for establishing a common set of formatting for a number of text markups. %%% beginning of sample code \version "2.19.82" \displayScheme \markup{\sans{\fontsize #10 "C"}} % Just used to show the scheme markup command -- this is what I'm trying #(define-markup-command (chord-name-markup layout props chord-name) (markup?) "Display a chord name in the desired formatting" (interpret-markup layout props (make-line-markup (#:sans (#:fontsize 10 chord-name) \markup \chord-name-markup "E" %%% end of code I've used displayScheme to get the representation of the markup function. I've found that is uses #:line so that I have to use make-line-markup. When I run this code, I get Processing `/var/folders/q5/88k2s1717qv1v7rq4tqz53k8gn/T/frescobaldi-fmnvoopw/tmpc0ltmn4y/document.ly' Parsing.../var/folders/q5/88k2s1717qv1v7rq4tqz53k8gn/T/frescobaldi-fmnvoopw/tmpc0ltmn4y/document.ly:9:32: In expression (#:fontsize 10 chord-name): /var/folders/q5/88k2s1717qv1v7rq4tqz53k8gn/T/frescobaldi-fmnvoopw/tmpc0ltmn4y/document.ly:9:32: Wrong type to apply: #:fontsize Apparently, in the context of make-line-markup I can't use #:fontsize as the first element in a list, because it's not applyable. How can I do this properly? Thanks, Carl ___ lilypond-user mailing list lilypond-user@gnu.org https://lists.gnu.org/mailman/listinfo/lilypond-user
Re: Trouble defining markup functiion
Carl Sorensen writes: > I'm trying to define a markup function for establishing a common set of > formatting for a number of text markups. > > %%% beginning of sample code > > \version "2.19.82" > > \displayScheme > \markup{\sans{\fontsize #10 "C"}} % Just used to show the scheme markup > command -- this is what I'm trying > > #(define-markup-command (chord-name-markup layout props chord-name) (markup?) >"Display a chord name in the desired formatting" >(interpret-markup layout props > (make-line-markup (#:sans (#:fontsize 10 chord-name) > > > \markup \chord-name-markup "E" > > %%% end of code > > I've used displayScheme to get the representation of the markup > function. I've found that is uses #:line so that I have to use > make-line-markup. #:sans is garbage outside of the markup macro. Also make-line-markup requires a list as its argument. Your original \markup{\sans{\fontsize #10 "C"}} contains two levels of spurious braces. Those generate spurious markup lists causing LilyPond to intersperse a \line call for converting back to a single markup. Any reason you don't use #{ \markup ... #} for constructing your markup? That way you don't need to replace LilyPond's expertise for constructing markups with your own. -- David Kastrup ___ lilypond-user mailing list lilypond-user@gnu.org https://lists.gnu.org/mailman/listinfo/lilypond-user
Re: Trouble defining markup functiion
On 2019-01-17 6:27 am, Carl Sorensen wrote: I'm trying to define a markup function for establishing a common set of formatting for a number of text markups. %%% beginning of sample code \version "2.19.82" \displayScheme \markup{\sans{\fontsize #10 "C"}} % Just used to show the scheme markup command -- this is what I'm trying #(define-markup-command (chord-name-markup layout props chord-name) (markup?) "Display a chord name in the desired formatting" (interpret-markup layout props (make-line-markup (#:sans (#:fontsize 10 chord-name) \markup \chord-name-markup "E" %%% end of code I've used displayScheme to get the representation of the markup function. I've found that is uses #:line so that I have to use make-line-markup. When I run this code, I get Processing `/var/folders/q5/88k2s1717qv1v7rq4tqz53k8gn/T/frescobaldi-fmnvoopw/tmpc0ltmn4y/document.ly' Parsing.../var/folders/q5/88k2s1717qv1v7rq4tqz53k8gn/T/frescobaldi-fmnvoopw/tmpc0ltmn4y/document.ly:9:32: In expression (#:fontsize 10 chord-name): /var/folders/q5/88k2s1717qv1v7rq4tqz53k8gn/T/frescobaldi-fmnvoopw/tmpc0ltmn4y/document.ly:9:32: Wrong type to apply: #:fontsize Apparently, in the context of make-line-markup I can't use #:fontsize as the first element in a list, because it's not applyable. How can I do this properly? I would sidestep trying to do the markup in pure Scheme and use #{ #} instead: #(define-markup-command (chord-name-markup layout props chord-name) (markup?) "Display a chord name in the desired formatting" (interpret-markup layout props #{ \markup \sans \fontsize #10 $chord-name #})) NOTE: I omitted some of the curly braces, since they were not needed. -- Aaron Hill ___ lilypond-user mailing list lilypond-user@gnu.org https://lists.gnu.org/mailman/listinfo/lilypond-user
Getting spanner length
Dear list! I’m all new to lily pond and trying to create a custom spanner (a couple of parallel lines connecting some of the holes of two fingering charts). To hack this together I would need the length of the spanner I’m modifying or replacing. I’ve put this piece of code together to extract it and can’t understand what mistake I’ve made: \version "2.18.2" \relative c'' { \once \override TextSpanner.stencil = #(lambda (grob) (let (grob-X (interval-length (ly:stencil-extent (ly:grob-property grob 'stencil) X))) (make-line-stencil .2 1 1 grob-X 4) ) ) d \startTextSpan c b a \stopTextSpan } I attempted to abstract it from this piece of code https://www.mail-archive.com/lilypond-user@gnu.org/msg81685.html Do you have any other sources or better suggestions for custom spanners? This doesn’t have to be very complex or be able to cover line breaks. Thanks a lot! /Leo ___ lilypond-user mailing list lilypond-user@gnu.org https://lists.gnu.org/mailman/listinfo/lilypond-user
Re: Getting spanner length
On 2019-01-17 6:43 am, Leo Correia de Verdier wrote: Dear list! I’m all new to lily pond and trying to create a custom spanner (a couple of parallel lines connecting some of the holes of two fingering charts). To hack this together I would need the length of the spanner I’m modifying or replacing. I’ve put this piece of code together to extract it and can’t understand what mistake I’ve made: \version "2.18.2" \relative c'' { \once \override TextSpanner.stencil = #(lambda (grob) (let (grob-X (interval-length (ly:stencil-extent (ly:grob-property grob 'stencil) X))) (make-line-stencil .2 1 1 grob-X 4) ) ) d \startTextSpan c b a \stopTextSpan } I attempted to abstract it from this piece of code https://www.mail-archive.com/lilypond-user@gnu.org/msg81685.html Do you have any other sources or better suggestions for custom spanners? This doesn’t have to be very complex or be able to cover line breaks. Two issues: - You are missing a set of parentheses for the let statement. - You are attempting to query a grob property from within the property. Try this: \version "2.18.2" \relative c'' { \once \override TextSpanner.stencil = #(lambda (grob) (let ((grob-X (interval-length (ly:stencil-extent (ly:line-spanner::print grob) X (make-line-stencil .2 1 1 grob-X 4))) d \startTextSpan c b a \stopTextSpan } -- Aaron Hill ___ lilypond-user mailing list lilypond-user@gnu.org https://lists.gnu.org/mailman/listinfo/lilypond-user
Re: System spacing for Certain
Aaron Hill wrote > On 2019-01-16 5:24 pm, Reggie wrote: >> First, are you saying that every time I want to manually adjust one >> staff in >> a system in one instance I must create a new voice just to hack this? >> Like >> you did? What about my original code itself used? > > You do not need the extra voice. I did that simply because the advice > in the notation reference is sound to follow. One should try to keep > matters of presentation (such as spacing) completely separate from the > musical content. It can muddy a score to have things like that messy > \overrideProperty stuck in the middle of notes. Additionally, it makes > it much harder to reuse musical content in different contexts without > resorting to tags. > > That all said, you can easily apply the \verticalSpacer to a musical > note in your staff rather than on a spacer in a separate voice. > >> Second, you mention that >> it's relative from PRIOR staff right? What if I want to move the top >> staff >> of a system up or down only for example as such? > > Technically, alignment-distances specifies the values *between* the > staves, so it doesn't affect space before the first or after the last. > In that case, you'd probably have to use something like extra-offset to > shift the entire system upwards or downwards, which is basically what > shifting the first staff would mean. > > If we're talking about the placeholder markup, simply use > ^\verticalSpacer so the markup appears above the staff in question. > This would work on a first staff of a system and force it to appear > further down on the paper. > > > -- Aaron Hill > > ___ > lilypond-user mailing list > lilypond-user@ > https://lists.gnu.org/mailman/listinfo/lilypond-user Thank you Aaron. However I also meant asking about the top staff of a system moving UP as well. So imagine you want to bump up a top staff of a system without moving other staffs in system. How so accomplish? -- Sent from: http://lilypond.1069038.n5.nabble.com/User-f3.html ___ lilypond-user mailing list lilypond-user@gnu.org https://lists.gnu.org/mailman/listinfo/lilypond-user
Re: select a note in a chord
I worked on your example, and here is the result. The "\drop n" function drop the nth note from above, an can be nested (to do drop 2 drop 4) The funcion "\rise n" function rise the nth note from below, an can be nested too The "\inversion n" function do the inversions of the chord. I'm sure there is a better way to write the inversion function, but I haven't find a way to program the repetition of a function in scheme. % #(define (move-a-note n direction) (lambda (music) (let* ((elts (ly:music-property music 'elements)) (l (length elts)) ;; if the direction is up, we count from the bottom note upward, ;; if the direction is down, we count from the top note downward (count-from (cond ((= direction up) (- n 1)) ((= direction down) (- l n ;; The user may not have entered the notes ;; from the lowest to the uppermost; ;; let’s extract the pitches… (pitches (map (lambda (x) (ly:music-property x 'pitch)) (filter (lambda (y) (music-is-of-type? y 'note-event)) elts))) ;; … and put them in order. (sorted (sort pitches ly:pitch= l n)) (begin ;; first apply the sorted pitches ;; to the actual notes. (map (lambda (e p) (ly:music-set-property! e 'pitch p)) elts sorted) ;; then transpose the specified note (list-set! elts count-from (ly:music-transpose (list-ref elts count-from) (ly:make-pitch (cond ;; transpose the note up or down, ;;depending on direction ((= direction up) +1) ((= direction down) -1)) 0) music))) %% drop a note of a chord, in num position from above drop = #(define-music-function (parser location num music) (integer? ly:music?) #{ \musicMap #(move-a-note num down) $music #}) %% rise a note of a chord, in num position from below rise = #(define-music-function (parser location num music) (integer? ly:music?) #{ \musicMap #(move-a-note num up) $music #}) inversion = #(define-music-function (parser location num music) (integer? ly:music?) (cond ((= num 1) #{ \rise 1 $music #}) ((= num 2) #{ \rise 1 \rise 1 $music #}) ((= num 3) #{ \rise 1 \rise 1 \rise 1 $music #}) ((= num 4) #{ \rise 1 \rise 1 \rise 1 \rise 1 $music #}) ((= num 5) #{ \rise 1 \rise 1 \rise 1 \rise 1 \rise 1 $music #}) ((= num 6) #{ \rise 1 \rise 1 \rise 1 \rise 1 \rise 1 \rise 1 $music #}) ((= num -1) #{ \drop 1 $music #}) ((= num -2) #{ \drop 1 \drop 1 $music #}) ((= num -3) #{ \drop 1 \drop 1 \drop 1 $music #}) ((= num -4) #{ \drop 1 \drop 1 \drop 1 \drop 1 $music #}) ((= num -5) #{ \drop 1 \drop 1 \drop 1 \drop 1 \drop 1 $music #}) ((= num -6) #{ \drop 1 \drop 1 \drop 1 \drop 1 \drop 1 \drop 1 $music #}) (else #{ $music #}) )) ac = \relative c' {2 \chordmode {c:maj es:6}} { <>^\markup "chords" \ac \bar "||" <>^\markup "drop 2" \drop 2 \ac \bar "||" <>^\markup "drop 4" \drop 4 \ac \bar "||" <>^\markup "drop 2 and 4" \drop 2 \drop 4 \ac \bar "||" <>^\markup "rise 1" \rise 1 \ac \bar "||" <>^\markup "rise 3" \rise 3 \ac \bar "||" <>^\markup "2nd inversion" \inversion 2 \ac \bar "||" <>^\markup "\"down\" inversion" \inversion -1 \ac \bar "||" } % Cheers. Davide Il 16/01/2019 00:15, David Kastrup ha scritto: Valentin Villenave writes: On 1/15/19, Davide Bonetti wrote: I modified (if (and (music-is-of-type? music 'event-chord) (> l n)) with (if (and (music-is-of-type? music 'event-chord) (>= l n)) Nice catch! I’ve updated the snippet as well. Additionally, beware that the LSR version uses #(define-music-function (parser location music) whereas the syntax for LilyPond 2.19 would be #(define-music-function (music) Not much to beware here since convert-ly knows its way around this and 2.19 will do argument counting in order to provide backwards compatibility. --- Questa e-mail è stata controllata per individuare virus con Avast antivirus. https://www.avast.com/antivirus #(define (move-a-note n direction) (lambda (music) (let* ((elts (ly:music-property music 'elements)) (l (length elts)) ;; if the direction is up, we count from the bottom note upward, ;; if the direction is down, we count from the top note downward ;; (strangely, jazzmen tend to ;; count from the top note downward). (count-from (cond ((= direction up) (- n 1)) ((
Re: setting fretboard diagrams at the top of the page
Hi Evan, Welcome to LilyPond! On 1/15/19, 11:10 AM, "Evan Levine" wrote: Good afternoon! I've got a few things I'm brewing right now, but the most pressing is that I'm looking to set all of the chord diagrams for a lead sheet at the top of the page under the title, and modify the spacing of the diagrams to be centered on the page and have padding between each diagram. The key here, in my opinion, is to set the fret diagrams as markups, rather than as music. Thanks so much! Here's my code: Great job on providing a small example! That was helpful to see what you intended. The only problem with the example is that it wouldn't completely compile, because the music and lyrics were missing. It's much easier if you provide those. Please forgive me for any oversight of the protocol here, as this is my first interaction with the mailing list. The only oversight I see is that you put your mail at the top of another unrelated post. Please don't post your reply to the top of a full post, and when you start a new thread, don't do it by replying to a previous post. With that said, here's how I'd attack your problem. I've created some markup functions to allow you to have control over size, spacing, etc. Beginning of sample code \version "2.19.82" \header { title = "Steven Universe Theme" composer = "Rebecca Sugar, Aivi & Surasshu" tagline = ##t } #(define chord-name-fontsize 6) #(define name-fretboard-separation .75) #(define different-separation 8) #(define same-separation 2) #(define or-vspace 1.75) #(define fret-formatting "s:2.2;w:4;h:3;d:0.37;f:1;") #(define c-fret "4-x;3-4-2;2-3-2;1-x;") #(define e-one-fret "c:4-2-4;4-4-3;3-4-3;2-4-3;1-x;") #(define e-two-fret "4-x;3-4-2;2-4-3;1-2-1;") #(define f-fret "4-x;3-5-2;2-5-3;1-3-1;") #(define fm-fret "4-x;3-5-2;2-4-3;1-3-1;") #(define-markup-command (chord-name-markup layout props chord-name) (markup?) "Display a chord name in the desired formatting" (interpret-markup layout props #{ \markup \sans \fontsize #chord-name-fontsize $chord-name #} )) #(define-markup-command (name-and-fret-markup layout props chord-name fret-diagram) (markup? markup?) "Display a chord name and fretboard as stacked markups separated by name-fretboard-separation" (interpret-markup layout props #{ \markup \center-column { \chord-name-markup $chord-name \vspace #name-fretboard-separation $fret-diagram } #})) #(define-markup-command (or-markup layout props or-text) (markup?) "Display a separator between alternative fretboards" (interpret-markup layout props #{ \markup \center-column { \vspace #or-vspace \chord-name-markup $or-text } #})) \markup \line { \name-and-fret-markup "C" \fret-diagram #(string-append fret-formatting c-fret) \hspace #different-separation \center-column { \name-and-fret-markup "E" \line { \fret-diagram #(string-append fret-formatting e-one-fret) \hspace #same-separation \or-markup "or" \hspace #same-separation \fret-diagram#(string-append fret-formatting e-two-fret) \hspace #same-separation \or-markup "or" \hspace #same-separation \fret-diagram#(string-append fret-formatting e-two-fret) } } \hspace #different-separation \name-and-fret-markup "F" \fret-diagram #(string-append fret-formatting f-fret) \hspace #different-separation \center-column { \name-and-fret-markup "Fm" \fret-diagram #(string-append fret-formatting fm-fret) } } \score { << \new ChordNames { c1 e f c f } \new Staff { \new Voice = "melody" { \repeat unfold 5 {c'4 d' e' f'} } } \new Lyrics { \lyricsto "melody" { \repeat unfold 5 {tra la la la } } } >> } end of sample code HTH, Carl ___ lilypond-user mailing list lilypond-user@gnu.org https://lists.gnu.org/mailman/listinfo/lilypond-user
Re: Trouble defining markup functiion
On 1/17/19, 8:02 AM, "David Kastrup" wrote: > > I've used displayScheme to get the representation of the markup > function. I've found that is uses #:line so that I have to use > make-line-markup. #:sans is garbage outside of the markup macro. Also make-line-markup requires a list as its argument. That's what I thought, but I couldn't find it documented. Your original \markup{\sans{\fontsize #10 "C"}} contains two levels of spurious braces. Those generate spurious markup lists causing LilyPond to intersperse a \line call for converting back to a single markup. I thought I copied that code from the NR, but I can't find it, so I must not have. Any reason you don't use #{ \markup ... #} for constructing your markup? That way you don't need to replace LilyPond's expertise for constructing markups with your own. Only because of ignorance. The last time I spent serious time writing markup functions, #{ ... #} wasn't available. Thanks for pointing it out to me, and again reminding me how much your work has improved the usability of LilyPond! On 1/17/19, 8:05 AM, "Aaron Hill" wrote: I would sidestep trying to do the markup in pure Scheme and use #{ #} instead: #(define-markup-command (chord-name-markup layout props chord-name) (markup?) "Display a chord name in the desired formatting" (interpret-markup layout props #{ \markup \sans \fontsize #10 $chord-name #})) Thanks for the help, Aaron. As both you and David mentioned, that was the right way to go about it. Thanks, Carl ___ lilypond-user mailing list lilypond-user@gnu.org https://lists.gnu.org/mailman/listinfo/lilypond-user
Re: Trouble defining markup functiion
Carl Sorensen writes: > On 1/17/19, 8:02 AM, "David Kastrup" wrote: > > > > > I've used displayScheme to get the representation of the markup > > function. I've found that is uses #:line so that I have to use > > make-line-markup. > > #:sans is garbage outside of the markup macro. Also make-line-markup > requires a list as its argument. > > That's what I thought, but I couldn't find it documented. It's probably more implied than documented. > Your original > \markup{\sans{\fontsize #10 "C"}} > > contains two levels of spurious braces. Those generate spurious markup > lists causing LilyPond to intersperse a \line call for converting back > to a single markup. > > I thought I copied that code from the NR, but I can't find it, so I > must not have. Or it has been simplified in the mean time. > Any reason you don't use #{ \markup ... #} for constructing your markup? > That way you don't need to replace LilyPond's expertise for constructing > markups with your own. > > Only because of ignorance. The last time I spent serious time writing > markup functions, #{ ... #} wasn't available. For markups. > Thanks for pointing it out to me, and again reminding me how much your > work has improved the usability of LilyPond! Well, this approach calls the parser at runtime. Certainly less efficient than calling a macro (which usually is already called at compile time anyway). This does not really increase usability (you cannot actually do more than you could do without) but it does lower the barrier of entry and gives more experienced developers a chance to "solve" other people's problems in a manner where they don't need to frequently visit the mailing lists for what amounts to elaboration on the same kind of question. Which does improve the usability of the mailing lists. Basically it's flush mounting of LilyPond's wiring. More complex than on-wall mounting, worse when maintenance is needed, but users don't keep stumbling over and tearing stuff. Until they try hanging up pictures, of course. -- David Kastrup ___ lilypond-user mailing list lilypond-user@gnu.org https://lists.gnu.org/mailman/listinfo/lilypond-user
Re: select a note in a chord
On 1/17/19, Davide Bonetti wrote: > I worked on your example, and here is the result. Nice! > I'm sure there is a better way to write the inversion function, but I > haven't find a way to program the repetition of a function in scheme. This is certainly not the most elegant way, but it seems to work: inversion = #(define-music-function (num music) (integer? ly:music?) (let ((str "") (up? (> num 0))) (map (lambda (x) (set! str (string-append str (if up? "\\rise 1 " "\\drop 1 "))) str) (iota (abs num))) #{ $(ly:parser-include-string str) $music #})) Can you verify that it works as you intended? (If you’re running 2.18, you’ll need to add "parser" after ly:parser-include-string.) Cheers, V. ___ lilypond-user mailing list lilypond-user@gnu.org https://lists.gnu.org/mailman/listinfo/lilypond-user
Re: select a note in a chord
Valentin Villenave writes: > On 1/17/19, Davide Bonetti wrote: >> I worked on your example, and here is the result. > > Nice! > >> I'm sure there is a better way to write the inversion function, but I >> haven't find a way to program the repetition of a function in scheme. > > This is certainly not the most elegant way, but it seems to work: > > inversion = > #(define-music-function (num music) (integer? ly:music?) >(let ((str "") > (up? (> num 0))) > (map (lambda (x) > (set! str > (string-append str > (if up? "\\rise 1 " "\\drop 1 "))) > str) >(iota (abs num))) There is append-map but seriously? (string-concatenate (make-list (abs num) (if (negative? num) "\\drop 1 " "\\rise 1 "))) > #{ $(ly:parser-include-string str) $music #})) This is not really an issue for string-manipulation. > Can you verify that it works as you intended? (If you’re running 2.18, > you’ll need to add "parser" after ly:parser-include-string.) And parser location before num in (num music). Let's rather do this in a sane manner: inversion = #(define-music-function (num music) (integer? ly:music?) (let loop ((num num) (music music)) (cond ((zero? num) music) ((negative? num) (loop (1+ num) (drop 1 music)) (else (loop (1- num) (rise 1 music))) Assuming 2.18, music functions are not directly callable from Scheme which would render this as inversion = #(define-music-function (parser location num music) (integer? ly:music?) (let loop ((num num) (music music)) (cond ((zero? num) music) ((negative? num) (loop (1+ num) #{ \drop 1 #music #})) (else (loop (1- num) #{ \rise 1 #music #}) This does not mess with internal parsers. And the 2.19 version does not even engage the parser for the looping. -- David Kastrup ___ lilypond-user mailing list lilypond-user@gnu.org https://lists.gnu.org/mailman/listinfo/lilypond-user
Re: select a note in a chord
On 1/18/19, David Kastrup wrote: > This is not really an issue for string-manipulation. Agreed. Nevertheless, I was pleasantly surprised to see that ly:parser-include-string could accept an incomplete expression. (Previously, ly:parser-parse-string would have been much less flexible here.) > Let's rather do this in a sane manner: Indeed, a named "let" loop is clearly the preferred way to go! That being said, I still wonder if there’d be any way of making it work with either iota or make-list without having to go through string manipulations. (It would remove the need for a loop with an incremented counter.) And btw, why does mapping onto (iota num) require a lambda (x) function even though that x argument does absolutely nothing? My instinct would be to use lambda (), but that throws an error. >((negative? num) (loop (1+ num) #{ \drop 1 #music #})) >(else (loop (1- num) #{ \rise 1 #music #}) Why #music and not $music inside the #{ #}? (I suspect there’s no difference in this case, but $music is the more familiar syntax inherited from before your parser/lexer improvements.) V. ___ lilypond-user mailing list lilypond-user@gnu.org https://lists.gnu.org/mailman/listinfo/lilypond-user
Re: select a note in a chord
Valentin Villenave writes: > On 1/18/19, David Kastrup wrote: >> This is not really an issue for string-manipulation. > > Agreed. Nevertheless, I was pleasantly surprised to see that > ly:parser-include-string could accept an incomplete expression. > (Previously, ly:parser-parse-string would have been much less flexible > here.) > >> Let's rather do this in a sane manner: > > Indeed, a named "let" loop is clearly the preferred way to go! > > That being said, I still wonder if there’d be any way of making it > work with either iota or make-list without having to go through string > manipulations. (It would remove the need for a loop with an > incremented counter.) You can use something like (fold (if (negative? num) drop rise) music (make-list (abs num) 1)) but I don't like creating lists for the sake of controlling loop size. > And btw, why does mapping onto (iota num) require a lambda (x) > function even though that x argument does absolutely nothing? My > instinct would be to use lambda (), but that throws an error. You cannot call functions with a different number of arguments than they are defined. A map is a _map_. Of course it takes an argument. If you want to express "this function ignores whatever arguments it may receives" you can write (lambda _ ... ) and the whole argument list would be assigned to _ (by convention a subsequently ignored binding). >>((negative? num) (loop (1+ num) #{ \drop 1 #music #})) >>(else (loop (1- num) #{ \rise 1 #music #}) > > Why #music and not $music inside the #{ #}? (I suspect there’s no > difference in this case, but $music is the more familiar syntax > inherited from before your parser/lexer improvements.) #music is an as-is Scheme expression, $music is evaluated and copied before assigning a syntactical category. If you aren't using the expression elsewhere, those copies are unnecessary. I mean, it's documented. The "Extending LilyPond Guide" has this to say: 1.2.1 LilyPond Scheme syntax The Guile interpreter is part of LilyPond, which means that Scheme can be included in LilyPond input files. There are several methods for including Scheme in LilyPond. The simplest way is to use a hash mark ‘#’ before a Scheme expression. Now LilyPond’s input is structured into tokens and expressions, much like human language is structured into words and sentences. LilyPond has a lexer that recognizes tokens (literal numbers, strings, Scheme elements, pitches and so on), and a parser that understands the syntax, *note (lilypond-contributor)LilyPond grammar::. Once it knows that a particular syntax rule applies, it executes actions associated with it. The hash mark ‘#’ method of embedding Scheme is a natural fit for this system. Once the lexer sees a hash mark, it calls the Scheme reader to read one full Scheme expression (this can be an identifier, an expression enclosed in parentheses, or several other things). After the Scheme expression is read, it is stored away as the value for an ‘SCM_TOKEN’ in the grammar. Once the parser knows how to make use of this token, it calls Guile for evaluating the Scheme expression. Since the parser usually requires a bit of lookahead from the lexer to make its parsing decisions, this separation of reading and evaluation between lexer and parser is exactly what is needed to keep the execution of LilyPond and Scheme expressions in sync. For this reason, you should use the hash mark ‘#’ for calling Scheme whenever this is feasible. Another way to call the Scheme interpreter from LilyPond is the use of dollar ‘$’ instead of a hash mark for introducing Scheme expressions. In this case, LilyPond evaluates the code right after the lexer has read it. It checks the resulting type of the Scheme expression and then picks a token type (one of several ‘xxx_IDENTIFIER’ in the syntax) for it. It creates a _copy_ of the value and uses that for the value of the token. If the value of the expression is void (Guile’s value of ‘*unspecified*’), nothing at all is passed to the parser. This is, in fact, exactly the same mechanism that LilyPond employs when you call any variable or music function by name, as ‘\name’, with the only difference that the name is determined by the LilyPond lexer without consulting the Scheme reader, and thus only variable names consistent with the current LilyPond mode are accepted. The immediate action of ‘$’ can lead to surprises, see *note Importing Scheme in LilyPond::. Using ‘#’ where the parser supports it is usually preferable. Inside of music expressions, expressions created using ‘#’ _are_ interpreted as music. However, they are _not_ copied before use. If they are part of some structure that might still get used, you may need to use ‘ly:music-deep-copy’ explicitly. -- David Kastrup ___ lilypond-user mailing list lilypond-user@gnu.org https://lists.gnu.org/mai
Re: select a note in a chord
David Kastrup writes: > Valentin Villenave writes: > >> On 1/18/19, David Kastrup wrote: >>> This is not really an issue for string-manipulation. >> >> Agreed. Nevertheless, I was pleasantly surprised to see that >> ly:parser-include-string could accept an incomplete expression. >> (Previously, ly:parser-parse-string would have been much less flexible >> here.) >> >>> Let's rather do this in a sane manner: >> >> Indeed, a named "let" loop is clearly the preferred way to go! >> >> That being said, I still wonder if there’d be any way of making it >> work with either iota or make-list without having to go through string >> manipulations. (It would remove the need for a loop with an >> incremented counter.) > > You can use something like > (fold (if (negative? num) drop rise) > music > (make-list (abs num) 1)) > > but I don't like creating lists for the sake of controlling loop size. By the way: `drop' is a function imported from (slri slri-1) and it's probably not a good idea to redefine it. -- David Kastrup ___ lilypond-user mailing list lilypond-user@gnu.org https://lists.gnu.org/mailman/listinfo/lilypond-user
Springs and rods
Yet another annoying question about documentation from me. After figuring out how to make a glissando longer, and discovering this in the NR under the spanner interface: minimum-length (dimension, in staff space) Try to make a spanner at least this long, normally in the horizontal direction. This requires an appropriate callback for the springs-and-rods property. If added to a Tie, this sets the minimum distance between noteheads. I can only ask and I think reasonably where is this mystical springs-and-rods mechanism explained? Why does one need to do this: \override Glissando #'minimum-length = #4 \override Glissando #'springs-and-rods = #ly:spanner::set-spacing-rods How is one meant to know what an 'appropriate callback is'? What other callback would one use? And what for? I have to honestly say that if I could ever understand the lilypond internals I would readily volunteer to rewrite these sections in the NR, which occur far too often I am afraid. I've been using lilypond heavily for years, and sections like this simply make me feel dumb. Perhaps I missed something fundamental along the learning curve. None of this criticism is aimed at any person. I am well aware this sort of manual is reference and not tutorial. There used to be a series of computer publications called [X]: The Missing Manual. I feel we need the missing manual for lilypond. I don't know enough to write it. All help most appreciated. Andrew ___ lilypond-user mailing list lilypond-user@gnu.org https://lists.gnu.org/mailman/listinfo/lilypond-user