Implementing a counter in markup text
This snippet shows how to implement a counter in LilyPond for use in markup texts. Whenever you call the \counter #"name" markup function, the counter named name will be increased by one and the new value will be printed as a text markup. The first call will print “1” by default. Example:
\markup { Initial value of the counter: \counter #"mycounter". Second call: \counter #"mycounter" }
The snippet also implements a \setcounter #"name" newvalue markup command to set the the counter to a specific value and print it out.
One can have an arbitrary number of simultaneous counters, each indicated by its own name (as a string).
The storage of the counter values is implemented as a global alist counter-alist (Scheme/Guile's concept of a hash), where the counter command simply extracts the current value, increases it by one and stores it back in the alist.
\version "2.24.0"
%% http://lsr.di.unimi.it/LSR/Item?id=543
\paper { tagline = ##f }
%here starts the snippet:
#(define counter-alist '())
#(define-markup-command (counter layout props name) (string?)
"Increases and prints out the value of the given counter named @var{name}.
If the counter does not yet exist, it is initialized with 1."
(let* ((oldval (assoc-ref counter-alist name))
(newval (if (number? oldval) (+ oldval 1) 1)))
(set! counter-alist (assoc-set! counter-alist name newval))
(interpret-markup layout props
(markup (number->string newval)))))
#(define-markup-command (setcounter layout props name value) (string? number?)
"Set the given counter named @var{name} to the given @var{value} and prints
out the value. The counter does not yet have to exist."
(set! counter-alist (assoc-set! counter-alist name (- value 1)))
(interpret-markup layout props (make-counter-markup name)))
\markup { Initial value of the counter: \counter #"mycounter". Second call: \counter #"mycounter" }
\markup { It is increasing: \counter #"mycounter" }
\markup { A second counter: \counter #"myothercounter" }
\markup { First counter is increasing: \counter #"mycounter" }
\markup { Second counter is increasing: \counter #"myothercounter" }
\markup { Setting to a specific value works, too: }
\markup { Set first counter to 15: \setcounter #"mycounter" #15 }
\markup { It is increasing: \counter #"mycounter" }
\markup { It is increasing: \counter #"mycounter" }
\markup { It is increasing: \counter #"mycounter" }
\markup { It is increasing: \counter #"mycounter" }
\markup { It is increasing: \counter #"mycounter" }
\markup { Second counter is increasing: \counter #"myothercounter" }