[ << Interfaces for programmers ] | [Top][Contents][Index][ ? ] | [ Literature list >> ] | ||
[ < How markups work internally ] | [ Up : Markup programmer interface ] | [ New markup list command definition > ] |
6.4.3 New markup command definition
New markup commands can be defined
with the define-markup-command
Scheme macro.
(define-markup-command (command-name layout props arg1 arg2 ...) (arg1-type? arg2-type? ...) ..command body..) |
The arguments are
- argi
ith command argument
- argi-type?
a type predicate for the ith argument
- layout
the ‘layout’ definition
- props
a list of alists, containing all active properties.
As a simple example, we show how to add a \smallcaps
command,
which selects a small caps font. Normally we could select the
small caps font,
\markup { \override #'(font-shape . caps) Text-in-caps }
This selects the caps font by setting the font-shape
property to
#'caps
for interpreting Text-in-caps
.
To make the above available as \smallcaps
command, we must
define a function using define-markup-command
. The command should
take a single argument of type markup
. Therefore the start of the
definition should read
(define-markup-command (smallcaps layout props argument) (markup?)
What follows is the content of the command: we should interpret
the argument
as a markup, i.e.,
(interpret-markup layout … argument)
This interpretation should add '(font-shape . caps)
to the active
properties, so we substitute the following for the … in the
above example:
(cons (list '(font-shape . caps) ) props)
The variable props
is a list of alists, and we prepend to it by
cons’ing a list with the extra setting.
Suppose that we are typesetting a recitative in an opera and
we would like to define a command that will show character names in a
custom manner. Names should be printed with small caps and moved a
bit to the left and top. We will define a \character
command
which takes into account the necessary translation and uses the newly
defined \smallcaps
command:
#(define-markup-command (character layout props name) (string?) "Print the character name in small caps, translated to the left and top. Syntax: \\character #\"name\"" (interpret-markup layout props (markup #:hspace 0 #:translate (cons -3 1) #:smallcaps name)))
There is one complication that needs explanation: texts above and below
the staff are moved vertically to be at a certain distance (the
padding
property) from the staff and the notes. To make sure
that this mechanism does not annihilate the vertical effect of our
#:translate
, we add an empty string (#:hspace 0
) before the
translated text. Now the #:hspace 0
will be put above the notes,
and the
name
is moved in relation to that empty string. The net effect is
that the text is moved to the upper left.
The final result is as follows:
{ c''^\markup \character #"Cleopatra" e'^\markup \character #"Giulio Cesare" }
We have used the caps
font shape, but suppose that our font
does not have a small-caps variant. In that case we have to fake
the small caps font by setting a string in upcase with the first
letter a little larger:
#(define-markup-command (smallcaps layout props str) (string?) "Print the string argument in small caps." (interpret-markup layout props (make-line-markup (map (lambda (s) (if (= (string-length s) 0) s (markup #:large (string-upcase (substring s 0 1)) #:translate (cons -0.6 0) #:tiny (string-upcase (substring s 1))))) (string-split str #\Space)))))
The smallcaps
command first splits its string argument into
tokens separated by spaces ((string-split str #\Space)
); for
each token, a markup is built with the first letter made large and
upcased (#:large (string-upcase (substring s 0 1))
), and a
second markup built with the following letters made tiny and upcased
(#:tiny (string-upcase (substring s 1))
). As LilyPond
introduces a space between markups on a line, the second markup is
translated to the left (#:translate (cons -0.6 0) ...
). Then,
the markups built for each token are put in a line by
(make-line-markup ...)
. Finally, the resulting markup is passed
to the interpret-markup
function, with the layout
and
props
arguments.
Note: there is now an internal command \smallCaps
which can
be used to set text in small caps. See
Text markup commands, for details.
Known issues and warnings
Currently, the available combinations of arguments (after the standard
layout and props arguments) to a markup command defined with
define-markup-command
are limited as follows.
- (no argument)
- list
- markup
- markup markup
- scm
- scm markup
- scm scm
- scm scm markup
- scm scm markup markup
- scm markup markup
- scm scm scm
In the above table, scm represents native Scheme data types like ‘number’ or ‘string’.
As an example, it is not possible to use a markup command foo
with
four arguments defined as
#(define-markup-command (foo layout props num1 str1 num2 str2) (number? string? number? string?) ...)
If you apply it as, say,
\markup \foo #1 #"bar" #2 #"baz"
lilypond
complains that it cannot parse foo
due to its
unknown Scheme signature.
[ << Interfaces for programmers ] | [Top][Contents][Index][ ? ] | [ Literature list >> ] | ||
[ < How markups work internally ] | [ Up : Markup programmer interface ] | [ New markup list command definition > ] |
Andere Sprachen: español.