this looks pretty nice. thanks. this gives me food for thought.
On Wed, Oct 29, 2025 at 10:57 AM Tina Petzel <[email protected]> wrote:
> > Hi all,
>
> Hi Marc,
>
> > I’d like to define helper markup commands so I can write compact examples
>
> > and (ideally) avoid repeating the same fragment twice.
>
> The issue here is that you want to preserve the actual Lilypond input
> code, which means you need to get it BEFORE it is parsed (which should also
> preserve all kinds of commends, whitespace, linebreaks, ...).
>
> Once the object is parsed there is no real way to get back to a lilypond
> input expression. There is the internal function `music->lily-string` used
> in `display-lily-music` you can use on a single music expression, but this
> does not get you what you want:
>
> E.g. if you do
>
> %%%
>
> notes = \relative c' {
>
> c d e f8 e | d4 g c,2
>
> }
>
> mus = \new Staff \with {
>
> instrumentName = "Violin"
>
> } \notes
>
> %%%
>
> and then `#(display-lily-music mus)` you’d get
>
> %%%
>
> \new Staff \with {
>
> \assign instrumentName
>
> } \absolute {
>
> c'4 d'4 e'4 f'8 e'8 |
>
> d'4 g'4 c'2
>
> }
>
> %%%
>
> which is definitely not what you want. So instead of parsing Lilypond code
> as code you’ll need to parse it as string and have it parsed later.
>
> For entering code as string either do `"..."` or (maybe nicer to enter)
> use `#{ ... #}`, but quote it: `#(quote #{ ... #})` or `#'#{ ... #}`. This
> results in a call where the second argument is the string in beween #{ ...
> #}.
>
> Now you can have that string parsed using `#(ly:parser-include-string
> string)`. But unless your code ends with some assignment of a variable you
> will not be able to capture the result this easily. Any music or score
> sitting at toplevel in a document (so with no assignment or anything) is
> passed to the function `toplevel-music-handler` or `toplevel-score-handler`.
>
> So to actually get access to such toplevel scores you’ll need to modify
> these handlers.
>
> See attached a file that does that: It includes
>
> * \rawString string: Wraps a string at line breaks
>
> * \collectScores string: Temporarily changes score and music handlers to
> collect scores in a list, returns that list.
>
> * \printScoreList: Turns a list of scores into a markup list of markup
> scores
>
> * \stack axis direction padding mlist: Use stack-stencils on a markup list
> (baseline-to-baseline spacing is not nice for spacing multiple scores).
>
> with this you can do `\column\rawString\code` to print the code,
> `\stack\printScoreList\collectScores\code` to print the scores.
>
> Note though that with this point-and-click does not work on the score.
> Also note that if you have multiple such scores changes to variables and
> values in the code will persist outside of the code example.
>
> For a more robust implementation it would be better to use an outside
> typesetting solution which prints the text, runs lilypond only on the
> snippet and includes the pdf (as would be the case with lilypond-book and
> lyluatex).
>
> Best regards,
>
> Tina
>
--
-- Marc