5

Say I wanted to re-define the format-mark-box-alphabet using a custom scm command.
How can this be done?

Here is a MWE where I would want both marks to be identical, with the double outline.

\version "2.24.1"

% Custom definition of the marker command
#(define-markup-command (format-mark-box-alphabet layout props text) (markup?)
  "Draw a double box around text."
  (interpret-markup layout props
    (markup #:override '(box-padding . 0.4) #:box
            #:override '(box-padding . 0.6) #:box text)))

\score {
  \new Staff {
    \set Score.rehearsalMarkFormatter = #format-mark-box-alphabet
    a2 a4 b
    \mark \default
    c'1 c'
    \mark \markup \format-mark-box-alphabet A
    a
    c'
  }
}

Current output:
Current output

Desired output:
Desired output

2 Answers 2

6

I think this is an XY question. Redefining a built-in procedure is called monkey-patching, and it is not advised, neither in LilyPond nor in most programming languages that allow it. Instead, you want to define your own rehearsal mark formatter format-mark-double-box-alphabet, which can be done like so (I've also used \etc for the markup command):

\version "2.24.1"

\markup double-box =
\markup \override #'(box-padding . 0.4) \box \override #'(box-padding . 0.6) \box \etc

#(define (format-mark-double-box-alphabet number context)
   #{ \markup \double-box #(format-mark-alphabet number context) #})

\score {
  \new Staff {
    \set Score.rehearsalMarkFormatter = #format-mark-double-box-alphabet
    a2 a4 b
    \mark \default
    c'1 c'
    \mark \default
    a
    c'
  }
}

Namely, the mark formatter is a Scheme procedure that takes a mark number and a context, and returns a markup. In this case, it's enough to use the built-in format-mark-alphabet procedure to get a letter from the number, then double-box it.

3
  • I have done as you suggest, going with a new function name for the modified box-alphabet formatter. The reason why I wanted to modify #format-mark-box-alphabet in the first place is that I was working on a stylesheet which, among other things, swaps out the music font. So I would have liked to have the stylesheet also ajust the styling of the box-formatter for it to match the overall style. I am accepting that this is not possible and that changing the style will require not only including the stylesheet, but also adjusting the box-formatter function call.
    – Bastian
    May 21, 2023 at 20:32
  • 1
    Why not just include the rehearsalMarkFormatter setting in the stylesheet? Do you really want to use that stylesheet with several scores, some which have format-mark-box-alphabet and some of which do not, and only double the boxes of those marks that are already boxed? May 21, 2023 at 21:20
  • You are right, I will include the rehearsalMarkFormatter in the stylesheet.
    – Bastian
    May 21, 2023 at 21:44
4

I fully support Jeans answer, but I want to fill in some details about why your version does not work. The reason is not that you are trying to redefine built-in procedures (which you can totally do, but usually would be a bad idea because in later code it becomes hard to understand if we are using the internal procedure or a modified one).

The reason for this is that you define your procedure only as markup command. Now, markup commands are a bit special in Lilypond, as they are defined in a separate scope (also they works slightly differently in when they are actually evaluated). So when you do

#(define-markup-command (test layout props) ()
   empty-stencil)

#(display test)

you will actually get an error, as guile won’t find the binding for test. In your case this means that while you define a markup command format-mark-box-alphabet, but this does not change the binding for format-mark-box-alphabet, so you are still using the old functions. Needless to say, if it actually tried to use the markup function it would encounter some issues, as Score.rehearsalMarkFormatter is not expecting a markup command, but a function with a different interface, as shown in Jean’s answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.