Referencia de la notación de GNU LilyPond: 6.4.3 New markup command definition

### 6.4.3 New markup command definition

Las instrucciones de marcado nuevas se pueden definir con el macro de Scheme `define-markup-command`.

    (define-markup-command (nombre-de-la-instruccion layout props arg1 arg2 ...)
                (arg1-type? arg2-type? ...)
      ..command body..)

Los argumentos son

argi

  i-ésimo argumento de la instrucción

argi-type?

  predicado de tipo para el argumento i-ésimo

layout

  la definición de ‘presentación’

props

  lista de listas asociativas, que contiene todas las propiedades activas.

Como ejemplo sencillo, mostramos cómo añadir una instrucción `\smallcaps`, que selecciona una tipografía de versalitas. Normalmente podríamos seleccionar la tipografía de versalitas,

>     \markup { \override #'(font-shape . caps) Texto-en-versalitas }

Esto selecciona la tipografía de versalitas mediante el establecimiento de la propiedad `font-shape` a `#'caps` para la interpretación de `Texto-en-versalitas`.

Para poner lo anterior disponible como la instrucción `\smallcaps`, tenemos que definir una función utilizando `define-markup-command`. La instrucción ha de tomar un argumento del tipo `markup`. Por tanto, el inicio de la definición ha de ser

>     (define-markup-command (smallcaps layout props argument) (markup?)

Lo que aparece a continuación es el contenido de la instrucción: debemos interpretar el `argument` como un marcado, es decir:

>     (interpret-markup layout … argument)

Esta interpretación tiene que añadir `'(font-shape . caps)` a las propiedades activas, por lo que sustituimos lo siguiente por los … en el ejemplo anterior:

>     (cons (list '(font-shape . caps) ) props)

La variable `props` es una lista de a-listas, y se lo anteponemos haciendo la operación cons de una lista con el ajuste adicional.

Supongamos que estamos tipografiando un recitativo de una ópera y nos gustaría definir una instrucción que presente los nombres de los personajes de una forma personalizada. Queremos que los nombres se impriman con versalitas y se desplacen un poco a la izquierda y hacia arriba. Definimos una instrucción `\character` que toma en cuenta la traslación necesaria y utiliza la instrucción `\smallcaps` recién definida:

>     #(define-markup-command (character layout props nombre) (string?)
>       "Imprimir el nombre del personaje en versalitas, desplazado a la izquierda y hacia
>       arriba.  Sintaxis: \\character #\"nombre\""
>       (interpret-markup layout props
>        (markup #:hspace 0 #:translate (cons -3 1) #:smallcaps nombre)))

Esta es una complicación que requiere una explicación: los textos por encima y por debajo del pentagrama se mueven verticalmente de forma que estén a una cierta distancia (la propiedad `padding`) del pentagrama y de las notas. Para asegurar que este mecanismo no anula el efecto de nuestro `#:translate`, añadimos una cadena vacía (`#:hspace 0`) antes del texto trasladado. Ahora el `#:hspace 0` se pone encima de las notas, y el `nombre` se mueve en relación a dicha cadena vacía. El efecto neto es que el texto se mueve hacia la izquierda y hacia arriba.

El resultado final es como sigue:

>     {
>       c''^\markup \character #"Cleopatra"
>       e'^\markup \character #"Giulio Cesare"
>     }

Hemos usado la forma de fuente tipográfica `caps`, pero supongamos que nuestra fuente no tiene la variante de versalitas. En ese caso tenemos que hacer una falsa fuente de mayúsculas pequeñas haciendo que la cadena en mayúsculas tenga la primera legra un poco mayor:

>     #(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)))))

La instrucción `smallcaps` primero divide su argumento de cadena en unidades o palabras separadas por espacios (`(string-split str #\Space)`); para cada unidad o palabra, se construye un marcado con la primera letra agrandada y en mayúscula (`#:large (string-upcase (substring s 0 1))`), y un segundo marcado construido con las letras siguientes reducidas de tamaño y en mayúsculas (`#:tiny (string-upcase (substring s 1))`). Como LilyPond introduce un espacio entre los marcados de una misma línea, el segundo marcado se traslada a la izquierda (`#:translate (cons -0.6 0) ...`). Después, los marcados construidos para cada palabra se ponen en una línea mediante `(make-line-markup ...)`. Finalmente, el marcado resultante se pasa a la función `interpret-markup`, con los argumentos `layout` y `props`.

Nota: ahora existe una instrucción interna `\smallCaps` que se puede usar para poner texto en versalitas. Consulte Text markup commands, para ver más detalles.

#### Advertencias y problemas conocidos

Actualmente las combinaciones de argumentos que hay disponibles (después de los argumentos estándar layout y props) para una instrucción de marcado definida con `define-markup-command` se limitan a la siguiente lista:

(ningún argumento)
list
markup
markup markup
scm
scm markup
scm scm
scm scm markup
scm scm markup markup
scm markup markup
scm scm scm

En la tabla de arriba, scm representa los tipos de datos nativos de Scheme como ‘number’ (número) o ‘string’ (cadena).

Como ejemplo, no es posible usar una instrucción de marcado `fulanito` con cuatro argumentos definida como

>     #(define-markup-command (fulanito layout props
>                              num1    str1    num2    str2)
>                             (number? string? number? string?)
>       ...)

Si la aplicamos como, digamos,

>     \markup \fulanito #1 #"mengano" #2 #"zutano"

`lilypond` protesta diciendo que no puede analizar `fulanito` debido a su firma de Scheme desconocida.

Other languages: English.

#### Manual de referencia de la notación