Jump to content

Implementing a counter in markup text: Difference between revisions

From LilyPond wiki
Import snippet from LSR
 
warning in red
 
(6 intermediate revisions by 3 users not shown)
Line 1: Line 1:
This snippet shows how to implement a counter in LilyPond for use in markup texts. Whenever you call the <code>\counter #&quot;name&quot;</code> markup function, the counter named <code>name</code> 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:
This snippet shows how to implement a counter in LilyPond for use in markup texts. Whenever you call the <code>\counter #"name"</code> markup function, the counter named <code>name</code> 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:


<code>\markup { Initial value of the counter: \counter #&quot;mycounter&quot;. Second call: \counter #&quot;mycounter&quot; }</code>
\markup {
  Initial value of the counter: \counter #"mycounter".
  Second call: \counter #"mycounter" }


The snippet also implements a <code>\setcounter #&quot;name&quot; newvalue</code> markup command to set the the counter to a specific value and print it out.
The snippet also implements a <code>\setcounter #"name" newvalue</code> 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).
One can have an arbitrary number of simultaneous counters, each indicated by its own name (as a string).
Line 9: Line 11:
The storage of the counter values is implemented as a global alist <code>counter-alist</code> (Scheme/Guile's concept of a hash), where the <code>counter</code> command simply extracts the current value, increases it by one and stores it back in the alist.
The storage of the counter values is implemented as a global alist <code>counter-alist</code> (Scheme/Guile's concept of a hash), where the <code>counter</code> command simply extracts the current value, increases it by one and stores it back in the alist.


<lilypond version="2.24.0" full>
<lilypond version="2.24">
%% http://lsr.di.unimi.it/LSR/Item?id=543
 
\paper { tagline = ##f }
 
%here starts the snippet:
 
#(define counter-alist '())
#(define counter-alist '())


Line 33: Line 29:
   (interpret-markup layout props (make-counter-markup name)))
   (interpret-markup layout props (make-counter-markup name)))


\markup { Initial value of the counter: \counter #"mycounter". Second call: \counter #"mycounter" }
\markup { Initial value of the counter: \counter #"mycounter". }
\markup { Second call: \counter #"mycounter" }
\markup { It is increasing: \counter #"mycounter" }
\markup { It is increasing: \counter #"mycounter" }
\markup { A second counter: \counter #"myothercounter" }
\markup { A second counter: \counter #"myothercounter" }
Line 41: Line 38:
\markup { Set first counter to 15: \setcounter #"mycounter" #15 }
\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 \with-color #red { Don't rush it: }
\markup { It is increasing: \counter #"mycounter" }
\markup { Three calls in a row: \counter #"mycounter", \counter #"mycounter" and \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" }
\markup { Second counter is increasing: \counter #"myothercounter" }
Line 50: Line 46:
[[Category:Text]]
[[Category:Text]]
[[Category:Scheme]]
[[Category:Scheme]]
[[Category:Snippet]]

Latest revision as of 09:05, 6 December 2025

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"

#(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". }
\markup { 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 \with-color #red { Don't rush it: }
\markup { Three calls in a row: \counter #"mycounter", \counter #"mycounter" and \counter #"mycounter" }
\markup { It is increasing: \counter #"mycounter" }
\markup { Second counter is increasing: \counter #"myothercounter" }