Search code examples
drycode-duplicationlilypond

What language mechanisms does Lilypond have for simple abbreviations, to avoid code duplication?


In , I often find myself writing things like this

\version "2.14.2"
{
  r2 c2 | gis'8 gis gis gis gis gis gis gis |
}

or this

\version "2.14.2"
{
  \time 3/4 \clef bass \relative es,
  {
    <es \parenthesize es'>8\staccato g bes
    <es, \parenthesize es'>8\staccato g c
  }
}

where I repeatedly double some note one octave higher, parenthesized.

I have scoured the Lilypond documentation, but have not found easy mechanisms to avoid this duplication. A more complex way is apparently to write a music function, but that seems to require stepping out into Scheme.

The only mechanism I have found to date is one for which I don't understand the mechanism:

\version "2.14.2"
S = #staccato
P = #parenthesize
{
  \time 3/4 \clef bass \relative es,
  {
    <es \P es'>8\S g bes <es, \P es'>8\S g c
  }
}

So: How can I write my own slightly more complex abbreviations in Lilypond, without escaping to Scheme?

Update. I edited back part of my question, to indicate that (1) I'm currently using 2.14.2, which is current on Ubuntu 12.04 LTS; (2) in my second example, after the bes I want to go back to the previous es, not one octave higher: and since I'm always working in \relative mode I intentionally wrote es,; (3) I'm looking for a way to abbreviate things like 'this note with the same one an octave higher, parenthesised'.


Solution

  • So it seems you have two questions here. For the first one, simply use the command \repeat unfold N { ...music... }, which is described in the documentation on this link. So your code above would become something like:

    \version "2.17.28"
    {
      c2 \repeat unfold 8 {gis'8} r2
      es1 | \repeat unfold 2{<es \parenthesize es'>8\staccato g bes4}
    }
    

    In case of chords, there is the special command q which repeats the last chord (it only repeat the pitches and it carries no information about duration, articulation, dynamics, etc):

    \version "2.17.28"
    {
      <a' c'' e''>4\p-> q q q |
      q-> q\ff q\p->\< q\! |
      d'8 e' q q q2 
    }
    

    You can also define shorter parts of the code and use them in the main code, such as:

    \version "2.17.28"
    A = {gis'8}
    B = {<es \parenthesize es'>8\staccato g bes4}
    
    {
      c2 \repeat unfold 8 {\A} r2 |
      es1 | \repeat unfold 2 {\B} | 
      \repeat unfold 16 {\A} |
      \repeat unfold 4 {\B}
    }
    

    As for your second question, I am also starting to learn to use functions on LilyPond. But well, it seems your code is equivalent to this code here, which is the most basic function (as far as I knew) in LilyPond:

    \version "2.17.28"
    S = #(define-event-function (parser location) ()
      #{ \staccato #}
    )
    
    P = #(define-event-function (parser location) ()
      #{ \parenthesize #}
    )
    
    {
    es1 | <es \P es'>8\S g bes <es, \P es'>\S g bes 
    }
    

    So if you just want to substitute some long text into your code, you can use this template: functionname = #(define-event-function (parser location) () #{ text #}), where functionname and text have to be changed, but the rest should remain the same. Applied, it looks like this:

    \version "2.17.28"
    test = #(define-event-function (parser location) ()
      #{ ^"test"\fermata\trill->\pp #}
    )
    {c''1\test | d'' }
    

    For something still a bit more complex, look at this example which is a music-function using notes as argument. Note how you can then manipulate where the arguments will be in the final output:

    \version "2.17.28"
    func = 
    #(define-music-function
      (parser location notes)
      (ly:music?)
      #{ 
        % generates 2 low pitches with cross notehead
        \override Staff.NoteHead.style = #'cross
        g,8 a,
    
        % reverts back to the normal noteheads and uses the notes in the argument of the function
        \revert Staff.NoteHead.style
        $notes   % these will be substituted by the arguments when you call this function on your main code
    
        % generates 4 low pitches with cross notehead
        \override Staff.NoteHead.style = #'cross
        g,8 a, b, c
        % reverts back to the normal noteheads for the rest of the code
        \revert Staff.NoteHead.style
      #}
    )
    
    {
      \func { c''4 } | d''1
    }
    

    Now if you want to do something more complex, then you will need to really study the documentation regarding music functions and try a lot by yourself. You can also check this and this links out.