@c -*- coding: utf-8; mode: texinfo; documentlanguage: es -*-
@c This file is part of extending.tely
@ignore
    Translation of GIT committish: 41c8bf63a7cc180746eace9b9e5278f541be0229

    When revising a translation, copy the HEAD committish of the
    version that you are working on.  See TRANSLATION for details.
@end ignore

@c \version "2.17.6"

@node Interfaces para programadores
@chapter Interfaces para programadores
@translationof Interfaces for programmers

Se pueden realizar trucos avanzados mediante el uso de Scheme.  Si no
está familiarizado con Scheme, le conviene leer nuestro tutorial de
Scheme, @ref{Tutorial de Scheme}.


@menu
* Bloques de código de LilyPond::
* Funciones de Scheme::
* Funciones musicales::
* Funciones de eventos::
* Funciones de marcado::
* Contextos para programadores::
* Funciones de callback::
* Código de Scheme en línea::
* Trucos difíciles::
@end menu

@node Bloques de código de LilyPond
@section Bloques de código de LilyPond
@translationof LilyPond code blocks

@cindex Bloques de código de LilyPond
@cindex LilyPond, bloques de código de
@funindex #@{ @dots{} #@}
@funindex $
@funindex #

La creación de expresiones musicales en Scheme puede ser una tarea
tediosa porque a veces presentan muchos niveles de profundidad de
anidamiento y el código resultante es grande.  Para algunas tareas
sencillas, esto puede evitarse utilizando bloques de código de
LilyPond, que permiten usar la sintaxis ordinaria de LilyPond
dentro de Scheme.

Los bloques de código de LilyPond tienen el siguiente aspecto:
@example
  #@{ @var{código de LilyPond} #@}
@end example

He aquí un ejemplo trivial:

@lilypond[verbatim,quote]
ritpp = #(define-event-function (parser location) ()
  #{ ^"rit." \pp #}
)

{ c'4 e'4\ritpp g'2 }
@end lilypond

Los bloques de código de LilyPond se pueden usar en cualquier
lugar en el que se pueda escribir código de Scheme.  El lector de
Scheme en efecto se modifica para que pueda incorporar bloques de
código de LilyPond y pueda ocuparse de las expresiones de Scheme
incrustadas que comienzan por @code{$} y@w{ }@code{#}.

@cindex parser (function argument)
@cindex location

El lector extrae el bloque de código de LilyPond y genera una
llamada en tiempo de ejecución al analizador sintáctico para que
interprete el código de LilyPond.  Las expresiones de Scheme
incrustadas en el código de LilyPond se evalúan dentro del entorno
lóexico del bloque de código de LilyPond, de manera que puede
accederse a todas las variables locales y los parámetros de
función que están disponibles en el punto en que se escribe el
bloque de código de LilyPond.  Las variables definidas en otros
módulos de Scheme, como los módulos que contienen bloques
@code{\header} y @code{\layout}, no están accesibles como
variables de Scheme, es decir, precedidas de@tie{}@code{#}, pero
se puede acceder a ellas como variables de LilyPond, es decir,
precedidas de@tie{}@code{\}.

Si @code{location} (véase @ref{Funciones de Scheme}) se refiere a una
posición de entrada válida (como lo hace normalmente dentro de las
funciones musicales o de Scheme), toda la música generada dentro
del bloque de código tiene su @samp{origin} establecido a
@code{location}.

Un bloque de código de LilyPond puede contener cualquier cosa que
podríamos utilizar en la parte derecha de una asignación.  Además, un
bloque de LilyPond vacío corresponde a una expresión musical vacía, y
un bloque de LilyPond que contiene varios eventos musicales se
convierte en una expresión de música secuencial.

@node Funciones de Scheme
@section Funciones de Scheme
@translationof Scheme functions
@cindex Scheme, funciones de (sintaxis de LilyPond)

Las @emph{funciones de Scheme} son procedimientos de Scheme que pueden
crear expresiones de Scheme a partir de código de entrada escrito en
la sintaxis de LilyPond.  Se pueden llamar desde prácticamente
cualquier lugar en el que se permita el uso de @code{#} para la
especificación de un valor en sintaxis de Scheme.  Mientras que Scheme
tiene funciones propias, este capítulo se ocupa de las funciones
@emph{sintácticas}, funciones que reciben argumentos especificados en
la sintaxis de LilyPond.

@menu
* Definición de funciones de Scheme::
* Uso de las funciones de Scheme::
* Funciones de Scheme vacías::
@end menu

@node Definición de funciones de Scheme
@subsection Definición de funciones de Scheme
@translationof Scheme function definitions
@funindex define-scheme-function

La forma general de la definición de una función de Scheme es:

@example
funcion =
#(define-scheme-function
     (parser location @var{arg1} @var{arg2} @dots{})
     (@var{tipo1?} @var{tipo2?} @dots{})
   @var{cuerpo})
@end example

@noindent
donde

@multitable @columnfractions .33 .66
@item @code{parser}
@tab tiene que ser literalmente @code{parser} para dar a los bloques de código
de LilyPond (@code{#@{}@dots{}@code{#@}}) acceso al analizador
sintáctico.

@item @code{location}
@tab tiene que ser literalmente @code{location} para ofrecer acceso al
objeto de situación de la entrada, que se usa para ofrecer
menssajes de error con nombres de archivo y números de línea.

@item @code{@var{argN}}
@tab @var{n}-ésimo argumento

@item @code{@var{typeN?}}
@tab un @emph{predicado de tipo} de Scheme para el que @code{@var{argN}}
debe devolver @code{#t}.

También existe una forma especial @code{(@emph{predicate?}
@emph{default})} para especificar argumentos opcionales.  Si el
argumento actual no está presente cuando se ll ama a la función, el
valor predeterminado se emplea en sustitución.  Los valores
predeterminados se evalúan en tiempo de definición (¡incluyendo los
bloques de código de LilyPond!), de manera que se necesitamos un valor
por omisión calculado en tiempo de ejecución, debemos escribir en su
lugar un valor especial que podamos reconocer fácilmente.  Si
escribimos el predicado entre paréntesis pero no lo seguimos por el
valor predeterminado, se usa @code{#f} como valor por omisión.  Los
valores por omisión no se verifican con @emph{predicate?} en tiempo de
definición ni en tiempo de ejecución: es nuestra responsabilidad
tratar con los valores que especifiquemos.  Los valores por omisión
que son expresiones musicales se copian mientras se establece
@code{origin} al parámetro @code{location}.

@item @code{@var{cuerpo}}
@tab una secuencia de formas de Scheme que se evalúan ordenadamente; la
última forma de la secuencia se usa como el valor de retorno de la
función de Scheme. Puede contener bloques de código de LilyPond
encerrados entre llaves con almohadillas
(@tie{}@w{@code{#@{@dots{}#@}}}@tie{}), como se describe en
@ref{Bloques de código de LilyPond}.  Dentro de los bloques de código
de LilyPond, use el símbolo @code{#} para hacer referencia a
argumentos de función (p.ej. @samp{#arg1}) o para iniciar una
expresión en línea de Scheme que contenga argumentos de función
(p.ej. @w{@samp{#(cons arg1 arg2)}}).  Donde las expresiones de Scheme
normales que usan @code{#} no funcionan, podríamos necesitar volver a
expresiones de Scheme inmediatas que usan @code{$}, como por ejemplo
@samp{$music}.

Si nuestra función devuelve una expresión musical, recibe un valor
@code{origin} útil.
@end multitable

@noindent
La idoneidad de los argumentos para los predicados viene determinada
mediante llamadas reales al predicado después de que LilyPond ya las
ha convertido en una expresión de Scheme.  Como consecuencia, el
argumento se puede especificar en la sintaxis de Scheme si se desea
(precedido de @code{#} o como resultado de haber llamado a una función
de Scheme), pero LilyPond también convierte algunas construcciones de
LilyPond en Scheme antes de hacer efectivamente la comprobación del
predicado sobre ellas.  Actualmente se encuentran entre ellas la
música, los post-eventos, las cadenas simples (entrecomilladas o no),
los números, los elementos de marcado y de listas de marcado, score
(partitura), book (libro), bookpart (parte de libro), las definiciones
de contexto y los bloques de definición de salida.

Para ciertos tipos de expresión (como la mayor parte de la música que
no está encerrada entre llaves) LilyPond necesita más allá de la
expresión misma para poder determinar su final.  Si tal expresión se
considerase un argumento opcional mediante la evaluación de su
predicado, LilyPond no podría recuperarse después de decidir que la
expresión no se corresponde con el parámetro.  Así, ciertas formas de
música necesitan ir encerradas entre llaves para poder considerarlas
como aceptables bajo algunas circunstancias.  LilyPond resuelve
algunas otras ambigüedades mediante la comprobación con funciones de
predicado: ¿es @samp{-3} un post-evento de digitación o un número
negativo?  ¿Es @code{"a" 4} en el modo de letra una cadena seguida por
un número, o un evento de letra con la duración @code{4}?  LilyPond
prueba el predicado del argumento sobre diversas interpretaciones
sucesivas hasta que lo consigue, con un orden diseñado para minimizar
las interpretaciones poco consistentes y la lectura por adelantado.

Por ejemplo, un predicado que acepta tanto expresiones musicales como
alturas consideraría que @code{c''} es una altura en lugar de una
expresión musical.  Las duraciones o post-eventos que siguieran
inmediatamente podrían no funcionar con dicha interpretación.  Así
pues, es mejor evitar los predicados excesivamente permisivos como
@code{scheme?} cuando la aplicación requeriría tipos de argumento más
específicos.

Para ver una lista de los predicados de tipo disponibles, consulte
@ruser{Predicados de tipo predefinidos}.

@seealso

Referencia de la notación:
@ruser{Predicados de tipo predefinidos}.

Archivos instalados:
@file{lily/music-scheme.cc},
@file{scm/c++.scm},
@file{scm/lily.scm}.


@node Uso de las funciones de Scheme
@subsection Uso de las funciones de Scheme
@translationof Scheme function usage

Las funciones de Scheme se pueden llamar casi desde cualquier lugar en
que puede escribirse una expresión de Scheme que comience con la
almohadilla@tie{}@code{#}.  Llamamos a una función de Scheme
escribiendo su nombre precedido de la barra invertida@tie{}@code{\}, y
seguido por sus argumentos.  Una vez que un argumento opcional no
corresponde a ningún argumento, LilyPond se salta este argumento y
todos los que le siguen, sustituyéndolos por su valor por omisión
especificado, y @q{recupera} el argumento que no correspondía al lugar
del siguiente argumento obligatorio.  Dado que el argumento recuperado
necesita ir a algún lugar, los argumentos opcionales no se consideran
realmente opcionales a no ser que vayan seguidos de un argumento
obligatorio.

Existe una excepción: si escribimos @code{\default} en el lugar de un
argumento opcional, este argumento y todos los argumentos opcionales
que le siguen se saltan y se sustituyen por sus valores
predeterminados.  Esto funciona incluso si no sigue ningún argumento
obligatorio porque @code{\default} no necesita recuperarse.  Las
instrucciones @code{mark} y @code{key} hacen uso de este truco para
ofrecer su comportamiento predeterminado cuando van seguidas solamente
por @code{\default}.

Aparte de los lugares en que se requiere un valor de Scheme hay
ciertos sitios en que se aceptan expresiones de almohadilla @code{#} y
se evalúan por sus efectos secundarios, pero por lo demás se ignoran.
Son, mayormente, los lugares en que también sería aceptable colocar
una asignación.

Dado que no es buena idea devolver valores que puedan malinterpretarse
en algún contexto, debería usar funciones de Scheme normales solo para
los casos en que siempre se devuelve un valor útil, y usar funciones
de Scheme vacías (@pxref{Funciones de Scheme vacías}) en caso
contrario.


@node Funciones de Scheme vacías
@subsection Funciones de Scheme vacías
@translationof Void scheme functions
@funindex define-void-function
@funindex \void

En ocasiones, un procedimiento se ejecuta con el objeto de llevar a
cabo alguna acción más que para devolver un valor.  Algunos lenguajes
de programación (como C y Scheme) usan las funciones para los dos
conceptos y se limitan a descartar el valor devuelto (usualmente
haciendo que cualquier expresión pueda actuar como instrucción,
ignorando el resultado devuelto).  Esto puede parecer inteligente pero
es propenso a errores: casi todos los compiladores de C de hoy en día
emiten advertencias cuando se descarta una expresión no vacía.  Para
muchas funciones que ejecutan una acción, los estándares de Scheme
declaran que el valor de retorno sea no especificado.  Guile, el
intérprete de Scheme de LilyPond, tiene un valor único
@code{*unspecified*} que en tales casos devuelve de forma usual (como
cuando se usa directamente @code{set!} sobre una variable), pero
desgraciadamente no de forma consistente.

Definir una función de LilyPond con @code{define-void-function}
asegura que se devuelve este valor especial, el único valor que
satisface el predicado @code{void?}.

@example
noApuntarYPulsar =
#(define-void-function
     (parser location)
     ()
   (ly:set-option 'point-and-click #f))
@dots{}
\noApuntarYPulsar   % desactivar la función de apuntar y pulsar
@end example

Si queremos evaluar una expresión sólo por su efecto colateral y no
queremos que se interprete ningún valor que pueda devolver, podemos
hacerlo anteponiendo el prefijo @code{\void}:

@example
\void #(hashq-set! some-table some-key some-value)
@end example

De esta forma podemos asegurar que LilyPond no asignará ningún
significado al valor devuelto, independientemente de dónde lo
encuentre.  También funciona para funciones musicales como
@code{\displayMusic}.

@node Funciones musicales
@section Funciones musicales
@translationof Music functions

@cindex funciones musicales

Las @emph{funciones musicales} son procedimientos de Scheme que pueden
crear automáticamente expresiones musicales, y se pueden usar para
simplificar enormemente el archivo de entrada.

@menu
* Definiciones de funciones musicales::
* Uso de las funciones musicales::
* Funciones de sustitución sencillas::
* Funciones de sustitución intermedias::
* Matemáticas dentro de las funciones::
* Funciones sin argumentos::
* Funciones musicales vacías::
@end menu


@node Definiciones de funciones musicales
@subsection Definiciones de funciones musicales
@translationof Music function definitions
@cindex definición de funciones musicales
@funindex define-music-function

La forma general para definir funciones musicales es:

@example
funcion =
#(define-music-function
     (parser location @var{arg1} @var{arg2} @dots{})
     (@var{tipo1?} @var{tipo2?} @dots{})
   @var{cuerpo})
@end example

@noindent
de forma bastante análoga a @ref{Definición de funciones de Scheme}.
Lo más probable es que el @var{cuerpo} sea un
@ref{Bloques de código de LilyPond,bloque de código de LilyPond}.

Para ver una lista de los predicados de tipo disponibles, consulte
@ruser{Predicados de tipo predefinidos}.

@seealso

Referencia de la notación:
@ruser{Predicados de tipo predefinidos}.

Archivos de inicio:
@file{lily/music-scheme.cc},
@file{scm/c++.scm},
@file{scm/lily.scm}.


@node Uso de las funciones musicales
@subsection Uso de las funciones musicales
@translationof Music function usage

Las funciones musicales se pueden actualmente utilizar en varios
lugares.  Dependiendo de dónde se usan, son de aplicación ciertas
restricciones para que sea posible su análisis sintáctico de forma
no ambigua.  El resultado que devuelve una función musical debe ser
compatible con el contexto desde el que se la llama.

@itemize
@item
En el nivel superior dentro de una expresión musical.  Aquí
no se aplica ninguna restricción.

@item
Como un post-evento, que comienza explícitamente con un indicador de
dirección (a elegir entre @code{-}, @code{^} @w{y @code{_}}).

En este caso, no podemos usar una expresión musical @emph{abierta}
como último argumento, que terminaría en una expresión musical
capaz de aceptar post-eventos adicionales.

@item
Como componente de un acorde.  La expresión devuelta debe ser
del tipo @code{rhythmic-event}, probablemente un @code{NoteEvent}.
@end itemize

@noindent
Las reglas especiales para los argumentos del final hacen posible
escribir funciones polimórficas como @code{\tweak} que se pueden
aplicar a construcciones distintas.

@node Funciones de sustitución sencillas
@subsection Funciones de sustitución sencillas
@translationof Simple substitution functions

Una función de sustitución sencilla es una función musical cuya
expresión musical de salida está escrita en código de LilyPond
y contiene argumentos de la función en la expresión de salida.
Están descritas en @ruser{Ejemplos de funciones de sustitución}.


@node Funciones de sustitución intermedias
@subsection Funciones de sustitución intermedias
@translationof Intermediate substitution functions

Las funciones de sustitución intermedias contienen una
mezcla de código de Scheme y de LilyPond
dentro de la expresión musical que se devuelve.

Algunas instrucciones @code{\override} requieren un argumento que
consiste en una pareja de números (llamada una @emph{célula cons} en
Scheme).

La pareja se puede pasar directamente dentro de la función musical,
usando una variable @code{pair?}:

@example
barraManual =
#(define-music-function
     (parser location principio-final)
     (pair?)
   #@{
     \once \override Beam.positions = #principio-final
   #@})

\relative c' @{
  \barraManual #'(3 . 6) c8 d e f
@}
@end example

De forma alternativa, los números que componen la pareja se pueden
pasar como argumentos separados, y el código de Scheme que se ha usado
para crear la pareja se puede incluir dentro de la expresión musical:

@lilypond[quote,verbatim,ragged-right]
manualBeam =
#(define-music-function
     (parser location beg end)
     (number? number?)
   #{
     \once \override Beam.positions = #(cons beg end)
   #})

\relative c' {
  \manualBeam #3 #6 c8 d e f
}
@end lilypond

@funindex \temporary
@cindex sobreescrituras temporales
@cindex temporales, sobreescrituras
@cindex propiedades, recuperar valor anterior

Las propiedades se mantienen conceptualmente utilizando una pila
por cada propiedad, por cada grob y por cada contexto.  Las
funciones musicales pueden requerir la sobreescritura de una o
varias propiedades durante el tiempo de duración de la función,
restaurándolas a sus valores previos antes de salir.  Sin embargo,
las sobreescrituras normales extraen y descartan la cima de la
pila de propiedades actual antes de introducir un valor en ella,
de manera que el valor anterior de la propiedad se pierde cuando
se sobreescribe.  Si se quiere preservar el valor anterior, hay
que preceder la instrucción @code{\override} con la palabra clave
@code{\temporary}, así:

@example
\temporary \override @dots{}
@end example

El uso de @code{\temporary} hace que se borre la propiedad
(normalmente fijada a un cierto valor) @code{pop-first} de la
sobreescritura, de forma que el valor anterior no se extrae de la
pila de propiedades antes de poner en ella el valor nuevo.  Cuando
una instrucción @code{\revert} posterior extrae el avlor
sobreescrito temporalmente, volverá a emerger el valor anterior.

En otras palabras, una llamada a @code{\temporary \override} y a
continuación otra a @code{\revert} sobre la misma propiedad, tiene
un valor neto que es nulo.  De forma similar, la combinación en
secuencia de @code{\temporary} y @code{\undo} sobre la misma
música que contiene las sobreescrituras, tiene un efecto neto
nulo.

He aquí un ejemplo de una función musical que utiliza lo expuesto
anteriormente.  El uso de @code{\temporary} asegura que los
valores de las propiedades @code{cross-staff} y @code{style} se
restauran a la salida a los valores que tenían cuando se llamó a
la función @code{crossStaff}.  Sin @code{\temporary}, a la salida
se habrían fijado los valores predeterminados.

@example
crossStaff =
#(define-music-function (parser location notes) (ly:music?)
  (_i "Create cross-staff stems")
  #@{
  \temporary \override Stem.cross-staff = #cross-staff-connect
  \temporary \override Flag.style = #'no-flag
  #notes
  \revert Stem.cross-staff
  \revert Flag.style
#@})
@end example


@node Matemáticas dentro de las funciones
@subsection Matemáticas dentro de las funciones
@translationof Mathematics in functions

Las funciones musicales pueden contar con programación de Scheme
además de la simple sustitución:

@lilypond[quote,verbatim,ragged-right]
AltOn =
#(define-music-function
     (parser location mag)
     (number?)
   #{
     \override Stem.length = #(* 7.0 mag)
     \override NoteHead.font-size =
       #(inexact->exact (* (/ 6.0 (log 2.0)) (log mag)))
   #})

AltOff = {
  \revert Stem.length
  \revert NoteHead.font-size
}

\relative c' {
  c2 \AltOn #0.5 c4 c
  \AltOn #1.5 c c \AltOff c2
}
@end lilypond

@noindent
Este ejemplo se puede reescribir de forma que pase expresiones
musicales:

@lilypond[quote,verbatim,ragged-right]
withAlt =
#(define-music-function
     (parser location mag music)
     (number? ly:music?)
   #{
     \override Stem.length = #(* 7.0 mag)
     \override NoteHead.font-size =
       #(inexact->exact (* (/ 6.0 (log 2.0)) (log mag)))
     #music
     \revert Stem.length
     \revert NoteHead.font-size
   #})

\relative c' {
  c2 \withAlt #0.5 { c4 c }
  \withAlt #1.5 { c c } c2
}
@end lilypond


@node Funciones sin argumentos
@subsection Funciones sin argumentos
@translationof Functions without arguments

En casi todos los casos, una función sin argumentos se debe escribir
con una variable:

@example
dolce = \markup@{ \italic \bold dolce @}
@end example

Sin embargo, en raras ocasiones puede ser de utilidad crear una
función musical sin argumentos:

@example
mostrarNumeroDeCompas =
#(define-music-function
     (parser location)
     ()
   (if (eq? #t (ly:get-option 'display-bar-numbers))
       #@{ \once \override Score.BarNumber.break-visibility = ##f #@}
       #@{#@}))
@end example

Para la impresión real de los números de compás donde se llama a esta
función, invoque a @command{lilypond} con

@example
lilypond -d display-bar-numbers ARCHIVO.ly
@end example


@node Funciones musicales vacías
@subsection Funciones musicales vacías
@translationof Void music functions

Una función musical debe devolver una expresión musical.  Si quiere
ejecutar una función exclusivamente por sus efectos secundarios,
debería usar @code{define-void-function}.  Pero
puede haber casos en los que a veces queremos producir una expresión
musical, y a veces no (como en el ejemplo anterior).  Devolver una
expresión musical @code{void} (vacía) por medio de @code{#@{ #@}} lo
hace posible.


@node Funciones de eventos
@section Funciones de eventos
@translationof Event functions
@funindex define-event-function
@cindex event functions

Para usar una función musical en el lugar de un evento, tenemos que
escribir un indicador de dirección antes de ella.  Pero a veces, ello
hace que se pierda la correspondencia con la sintaxis de las
construcciones que queremos sustituir.  Por ejemplo, si queremos
escribir instrucciones de matiz dinámico, éstos se adjuntan
habitualmente sin indicador de dirección, como @code{c'\pp}.  He aquí
una forma de escribir indicaciones dinámicas arbitrarias:

@lilypond[quote,verbatim,ragged-right]
dyn=#(define-event-function (parser location arg) (markup?)
         (make-dynamic-script arg))
\relative c' { c\dyn pfsss }
@end lilypond

Podríamos hacer lo mismo usando una función musical, pero entonces
tendríamos que escribir siempre un indicador de dirección antes de
llamarla, como @code{@w{c-\dyn pfsss}}.


@node Funciones de marcado
@section Funciones de marcado
@translationof Markup functions

Los elementos de marcado están implementados como funciones de Scheme
especiales que producen un objeto @code{Stencil} dada una serie de
argumentos.


@menu
* Construcción de elementos de marcado en Scheme::
* Cómo funcionan internamente los elementos de marcado::
* Definición de una instrucción de marcado nueva::
* Definición de nuevas instrucciones de lista de marcado::
@end menu

@node Construcción de elementos de marcado en Scheme
@subsection Construcción de elementos de marcado en Scheme
@translationof Markup construction in Scheme

@cindex marcado, definir instrucciones de
@funindex \displayScheme

Las expresiones de marcado se representan internamente en Scheme
usando el macro @code{markup}:

@example
(markup @var{expr})
@end example

Para ver una expresión de marcado en su forma de Scheme, utilice
la instrucción @code{\displayScheme}:

@example
\displayScheme
\markup @{
  \column @{
    \line @{ \bold \italic "hola" \raise #0.4 "mundo" @}
    \larger \line @{ fulano fulanito menganito @}
  @}
@}
@end example

@noindent
La compilación del código anterior envía a la consola lo
siguiente:

@example
(markup
  #:line
  (#:column
   (#:line
    (#:bold (#:italic "hola") #:raise 0.4 "mundo")
    #:larger
    (#:line
     (#:simple "fulano" #:simple "fulanito" #:simple "menganito")))))
@end example

Para evitar que el marcado se imprima en la página, use
@w{@samp{\void \displayScheme @var{marcado}}}.  Asimismo, como
ocurre con la instrucción @code{\displayMusic}, la salida de
@code{\displayScheme} se puede guardar en un archivo externo.
Véase @ref{Presentación de las expresiones musicales}.

@noindent
Este ejemplo muestra las principales reglas de traducción entre la
sintaxis del marcado normal de LilyPond y la sintaxis del marcado de
Scheme.  La utilización de @code{#@{ @dots{} #@}} para escribir en la
sintaxis de LilyPond será con frecuencia lo más conveniente, pero
explicamos cómo usar la macro @code{markup} para obtener una solución
sólo con Scheme.

@quotation
@multitable @columnfractions .3 .3
@item @b{LilyPond} @tab @b{Scheme}
@item @code{\markup marcado1} @tab @code{(markup marcado1)}
@item @code{\markup @{ marcado1 marcado2 @dots{} @}} @tab
        @code{(markup marcado1 marcado2 @dots{} )}
@item @code{\instruccion} @tab @code{#:instruccion}
@item @code{\variable} @tab @code{variable}
@item @code{\center-column @{ @dots{} @}} @tab
        @code{#:center-column ( @dots{} )}
@item @code{cadena} @tab @code{"cadena"}
@item @code{#argumento-de-scheme} @tab @code{argumento-de-scheme}
@end multitable
@end quotation

Todo el lenguaje Scheme está accesible dentro del macro @code{markup}.
Por ejemplo, podemos usar llamadas a funciones dentro de @code{markup}
para así manipular cadenas de caracteres.  Esto es útil si se están
definiendo instrucciones de marcado nuevas (véase
@ref{Definición de una instrucción de marcado nueva}).


@knownissues

El argumento markup-list de instrucciones como @code{#:line},
@code{#:center} y @code{#:column} no puede ser una variable ni el
resultado de la llamada a una función.

@lisp
(markup #:line (funcion-que-devuelve-marcados))
@end lisp

@noindent
no es válido.  Hay que usar las funciones @code{make-line-markup},
@code{make-center-markup} o @code{make-column-markup} en su lugar:

@lisp
(markup (make-line-markup (funcion-que-devuelve-marcados)))
@end lisp


@node Cómo funcionan internamente los elementos de marcado
@subsection Cómo funcionan internamente los elementos de marcado
@translationof How markups work internally

En un elemento de marcado como

@example
\raise #0.5 "ejemplo de texto"
@end example

@noindent
@code{\raise} se representa en realidad por medio de la función
@code{raise-markup}.  La expresión de marcado se almacena como

@example
(list raise-markup 0.5 (list simple-markup "ejemplo de texto"))
@end example

Cuando el marcado se convierte en objetos imprimibles (Stencils o
sellos), se llama la función @code{raise-markup} como

@example
(apply raise-markup
       @var{\objeto de marcado}
       @var{lista de listas asociativas de propiedades}
       0.5
       @var{el marcado "ejemplo de texto"})
@end example

Primero la función @code{raise-markup} crea el sello para la cadena
@code{ejemplo de texto}, y después eleva el sello Stencil en 0.5
espacios de pentagrama.  Este es un ejemplo bastante simple; en el
resto de la sección podrán verse ejemplos más complejos, así como en
@file{scm/define-markup-commands.scm}.


@node Definición de una instrucción de marcado nueva
@subsection Definición de una instrucción de marcado nueva
@translationof New markup command definition

Esta sección trata sobre la definición de nuevas instrucciones de
marcado.


@menu
* Sintaxis de la definición de instrucciones de marcado::
* Acerca de las propiedades::
* Un ejemplo completo::
* Adaptación de instrucciones incorporadas::
@end menu

@node Sintaxis de la definición de instrucciones de marcado
@unnumberedsubsubsec Sintaxis de la definición de instrucciones de marcado
@translationof Markup command definition syntax

Se pueden definir instrucciones de marcado nuevas usando el macro de
Scheme @code{define-markup-command}, en el nivel sintáctico superior.

@lisp
(define-markup-command (@var{nombre-de-la-instruccion} @var{layout} @var{props} @var{arg1} @var{arg2} @dots{})
    (@var{tipo-de-arg1?} @var{tipo-de-arg2?} @dots{})
    [ #:properties ((@var{propiedad1} @var{valor-predeterminado1})
                    @dots{}) ]
  @dots{}command body@dots{})
@end lisp

Los argumentos son

@table @code
@item @var{nombre-de-la-instruccion}
nombre de la instrucción de marcado
@item layout
la definición de @q{layout} (disposición).
@item props
una lista de listas asociativas, que contienen todas las propiedades
activas.
@item @var{argi}
argumento @var{i}-ésimo de la instrucción
@item @var{tipo-de-argi?}
predicado de tipo para el argumento @var{i}-ésimo
@end table

Si la instrucción utiliza propiedades de los argumentos @code{props},
se puede usar la palabra clave @code{#:properties} para especificar
qué propiedades se usan, así como sus valores predeterminados.

Los argumentos se distinguen según su tipo:
@itemize
@item un marcado, que corresponde al predicado de tipo @code{markup?};
@item una lista de marcados, que corresponde al predicado de tipo
@code{markup-list?};
@item cualquier otro objeto de Scheme, que corresponde a predicados de tipo como
@code{list?}, @code{number?}, @code{boolean?}, etc.
@end itemize

No existe ninguna limitación en el orden de los argumentos (después de
los argumentos estándar @code{layout} y @code{props}).  Sin embargo, las
funciones de marcado que toman un elemento de marcado como su último
argumento son un poco especiales porque podemos aplicarlas a una lista
de marcados y el resultado es una lista de marcados donde la función
de marcado (con los argumentos antecedentes especificados) se ha
aplicado a todos los elementos de la lista de marcados original.

Dado que la replicación de los argumentos precedentes para aplicar una
función de marcado a una lista de marcados es poco costosa
principalmente por los argumentos de Scheme, se evitan las caídas de
rendimiento simplemente mediante la utilización de argumentos de
Scheme para los argumentos antecedentes de las funciones de marcado
que toman un marcado como su último argumento.

@funindex \markup
@cindex markup macro
@funindex interpret-markup
Las instrucciones de marcado tienen un ciclo de vida más bien
complejo.  El cuerpo de la definición de una instrucción de marcado es
responsable de la conversión de los argumentos de la instrucción de
marcado en una expresión de sello que se devuelve.  Muy a menudo esto
se lleva a cabo llamando a la función @code{interpret-markup} sobre
una expresión de marcado, pasándole los argumentos @var{layout} y
@var{props}.  Por lo general, estos argumentos se conocen solamente en
una fase muy tardía de la composición tipográfica.  Las expresiones de
marcado ya tienen sus componentes ensamblados dentro de expresiones de
marcado cuando se expanden las instrucciones @code{\markup} (dentro de
una expresión de LilyPond) o la macro @code{markup} (dentro de
Scheme).  La evaluación y la comprobación de tipos de los argumentos
de la instrucción de marcado tiene lugar en el momento en que se
interpretan @code{\markup} o @code{markup}.

Pero la conversión real de expresiones de marcado en expresiones de
sello mediante la ejecución de los cuerpos de función de marcado solo
tienen lugar cuando se llama a @code{interpret-markup} sobre una
expresión de marcado.

@node Acerca de las propiedades
@unnumberedsubsubsec Acerca de las propiedades
@translationof On properties

Los argumentos @code{layout} y @code{props} de las instrucciones de
marcado traen a escena un contexto para la interpretación del marcado:
tamaño de la tipografía, grueso de línea, etc.

El argumento @code{layout} permite el acceso a las propiedades
definidas en los bloques @code{paper}, usando la función
@code{ly:output-def-lookup}.  Por ejemplo, el grueso de línea (el
mismo que el que se usa en las partituras) se lee usando:

@example
(ly:output-def-lookup layout 'line-width)
@end example

El argumento @code{props} hace accesibles algunas propiedades a las
instrucciones de marcado.  Por ejemplo, cuando se interpreta el
marcado del título de un libro, todas las variables definidas dentro
del bloque @code{\header} se añaden automáticamente a @code{props}, de
manera que el marcado del título del libro puede acceder al título del
libro, el autor, etc.  También es una forma de configurar el
comportamiento de una instrucción de marcado: por ejemplo, cuando una
instrucción utiliza tamaños de tipografía durante el procesado, el
tamaño se lee de @code{props} en vez de tener un argumento
@code{font-size}.  El que llama a una instrucción de marcado puede
cambiar el valor de la propiedad del tamaño de la tipografía con el
objeto de modificar el comportamiento.  Utilice la palabra clave
@code{#:properties} de @code{define-markup-command} para especificar
qué propiedades se deben leer a partir de los argumentos de
@code{props}.

El ejemplo de la sección siguiente ilustra cómo acceder y
sobreescribir las propiedades de una instrucción de marcado.


@node Un ejemplo completo
@unnumberedsubsubsec Un ejemplo completo
@translationof A complete example

El ejemplo siguiente define una instrucción de marcado para trazar un
rectángulo doble alrededor de un fragmento de texto.

En primer lugar, necesitamos construir un resultado aproximado
utilizando marcados.  Una consulta a @ruser{Instrucciones de marcado
de texto} nos muestra que es útil la instrucción @code{\box}:

@lilypond[quote,verbatim,ragged-right]
\markup \box \box HELLO
@end lilypond

Ahora, consideramos que es preferible tener más separación entre el
texto y los rectángulos.  Según la documentación de @code{\box}, esta
instrucción usa una propiedad @code{box-padding}, cuyo valor
predeterminado es 0.2.  La documentación también menciona cómo
sobreescribir este valor:

@lilypond[quote,verbatim,ragged-right]
\markup \box \override #'(box-padding . 0.6) \box A
@end lilypond

Después, el relleno o separación entre los dos rectángulos nos parece
muy pequeño, así que lo vamos a sobreescribir también:

@lilypond[quote,verbatim,ragged-right]
\markup \override #'(box-padding . 0.4) \box
     \override #'(box-padding . 0.6) \box A
@end lilypond

Repetir esta extensa instrucción de marcado una y otra vez sería un
quebradero de cabeza.  Aquí es donde se necesita una instrucción de
marcado.  Así pues, escribimos una instrucción de marcado
@code{double-box}, que toma un argumento (el texto).  Dibuja los dos
rectángulos y añade una separación.

@lisp
#(define-markup-command (double-box layout props text) (markup?)
  "Trazar un rectángulo doble rodeando el texto."
  (interpret-markup layout props
    #@{\markup \override #'(box-padding . 0.4) \box
            \override #'(box-padding . 0.6) \box @{ #text @}#@}))
@end lisp

o, de forma equivalente,

@lisp
#(define-markup-command (double-box layout props text) (markup?)
  "Trazar un rectángulo doble rodeando el texto."
  (interpret-markup layout props
    (markup #:override '(box-padding . 0.4) #:box
            #:override '(box-padding . 0.6) #:box text)))
@end lisp

@code{text} es el nombre del argumento de la instrucción, y
@code{markup?} es el tipo: lo identifica como un elemento de marcado.
La función @code{interpret-markup} se usa en casi todas las
instrucciones de marcado: construye un sello, usando @code{layout},
@code{props}, y un elemento de marcado.  En el segundo caso, la marca
se construye usando el macro de Scheme @code{markup}, véase
@ref{Construcción de elementos de marcado en Scheme}.  La
transformación de una expresión @code{\markup} en una expresión de
marcado de Scheme es directa.

La instrucción nueva se puede usar como sigue:

@example
\markup \double-box A
@end example

Sería buen hacer que la instrucción @code{double-box} fuera
personalizable: aquí, los valores de relleno @code{box-padding} son
fijos, y no se pueden cambiar por parte del usuario.  Además, sería
mejor distinguir la separación entre los dos rectángulos, del relleno
entre el rectángulo interno y el texto.  Así pues, introducimos una
nueva propiedad, @code{inter-box-padding}, para el relleno entre los
rectángulos.  El @code{box-padding} se usará para el relleno interno.
Ahora el código nuevo es como se ve a continuación:

@lisp
#(define-markup-command (double-box layout props text) (markup?)
  #:properties ((inter-box-padding 0.4)
                (box-padding 0.6))
  "Trazar un rectángulo doble rodeando el texto."
  (interpret-markup layout props
    #@{\markup \override #`(box-padding . ,inter-box-padding) \box
               \override #`(box-padding . ,box-padding) \box
               @{ #text @} #@}))
@end lisp

De nuevo, la versión equivalente que utiliza la macro de marcado sería:

@lisp
#(define-markup-command (double-box layout props text) (markup?)
  #:properties ((inter-box-padding 0.4)
                (box-padding 0.6))
  "Trazar un rectángulo doble rodeando el texto."
  (interpret-markup layout props
    (markup #:override `(box-padding . ,inter-box-padding) #:box
            #:override `(box-padding . ,box-padding) #:box text)))
@end lisp

Aquí, la palabra clave @code{#:properties} se usa de manera que las
propiedades @code{inter-box-padding} y @code{box-padding} se leen a
partir del argumento @code{props}, y se les proporcionan unos valores
predeterminados si las propiedades no están definidas.

Después estos valores se usan para sobreescribir las propiedades
@code{box-padding} usadas por las dos instrucciones @code{\box}.
Observe el apóstrofo invertido y la coma en el argumento de
@code{\override}: nos permiten introducir un valor de variable dentro
de una expresión literal.

Ahora, la instrucción se puede usar dentro de un elemento de marcado,
y el relleno de los rectángulos se puede personalizar:

@lilypond[quote,verbatim,ragged-right]
#(define-markup-command (double-box layout props text) (markup?)
  #:properties ((inter-box-padding 0.4)
                (box-padding 0.6))
  "Draw a double box around text."
  (interpret-markup layout props
    #{\markup \override #`(box-padding . ,inter-box-padding) \box
              \override #`(box-padding . ,box-padding) \box
              { #text } #}))

\markup \double-box A
\markup \override #'(inter-box-padding . 0.8) \double-box A
\markup \override #'(box-padding . 1.0) \double-box A
@end lilypond


@node Adaptación de instrucciones incorporadas
@unnumberedsubsubsec Adaptación de instrucciones incorporadas
@translationof Adapting builtin commands

Una buena manera de comenzar a escribir una instrucción de marcado
nueva, es seguir el ejemplo de otra instrucción ya incorporada.  Casi
todas las instrucciones de marcado que están incorporadas en LilyPond
se pueden encontrar en el archivo
@file{scm/define-markup-commands.scm}.

Por ejemplo, querríamos adaptar la instrucción @code{\draw-line}, para
que trace una línea doble.  La instrucción @code{\draw-line} está
definida como sigue (se han suprimido los comentarios de
documentación):

@lisp
(define-markup-command (draw-line layout props dest)
  (number-pair?)
  #:category graphic
  #:properties ((thickness 1))
  "@dots{}documentación@dots{}"
  (let ((th (* (ly:output-def-lookup layout 'line-thickness)
               thickness))
        (x (car dest))
        (y (cdr dest)))
    (make-line-stencil th 0 0 x y)))
@end lisp

Para definir una instrucción nueva basada en otra existente, copie la
definición y cámbiele el nombre.  La palabra clave @code{#:category}
se puede eliminar sin miedo, pues sólo se utiliza para generar
documentación de LilyPond, y no tiene ninguna utilidad para las
instrucciones de marcado definidas por el usuario.

@lisp
(define-markup-command (draw-double-line layout props dest)
  (number-pair?)
  #:properties ((thickness 1))
  "@dots{}documentación@dots{}"
  (let ((th (* (ly:output-def-lookup layout 'line-thickness)
               thickness))
        (x (car dest))
        (y (cdr dest)))
    (make-line-stencil th 0 0 x y)))
@end lisp

A continuación se añade una propiedad para establecer la separación
entre las dos líneas, llamada @code{line-gap}, con un valor
predeterminado de p.ej. 0.6:

@lisp
(define-markup-command (draw-double-line layout props dest)
  (number-pair?)
  #:properties ((thickness 1)
                (line-gap 0.6))
  "@dots{}documentación@dots{}"
  @dots{}
@end lisp

Finalmente, se añade el código para trazar las dos líneas.  Se usan
dos llamadas a @code{make-line-stencil} para trazar las líneas, y los
sellos resultantes se combinan usando @code{ly:stencil-add}:

@lilypond[quote,verbatim,ragged-right]
#(define-markup-command (my-draw-line layout props dest)
  (number-pair?)
  #:properties ((thickness 1)
                (line-gap 0.6))
  "..documentation.."
  (let* ((th (* (ly:output-def-lookup layout 'line-thickness)
                thickness))
         (dx (car dest))
         (dy (cdr dest))
         (w (/ line-gap 2.0))
         (x (cond ((= dx 0) w)
                  ((= dy 0) 0)
                  (else (/ w (sqrt (+ 1 (* (/ dx dy) (/ dx dy))))))))
         (y (* (if (< (* dx dy) 0) 1 -1)
               (cond ((= dy 0) w)
                     ((= dx 0) 0)
                     (else (/ w (sqrt (+ 1 (* (/ dy dx) (/ dy dx))))))))))
     (ly:stencil-add (make-line-stencil th x y (+ dx x) (+ dy y))
                     (make-line-stencil th (- x) (- y) (- dx x) (- dy y)))))

\markup \my-draw-line #'(4 . 3)
\markup \override #'(line-gap . 1.2) \my-draw-line #'(4 . 3)
@end lilypond


@node Definición de nuevas instrucciones de lista de marcado
@subsection Definición de nuevas instrucciones de lista de marcado
@translationof New markup list command definition

@funindex define-markup-list-command
@funindex interpret-markup-list

Las instrucciones de listas de marcado se definen con el macro de
Scheme @code{define-markup-list-command}, que es similar al macro
@code{define-markup-command} descrito en @ref{Definición de una
instrucción de marcado nueva}, excepto que donde éste devuelve un
sello único, aquél devuelve una lista de sellos.

En el siguiente ejemplo se define una instrucción de lista de marcado
@code{\paragraph}, que devuelve una lista de líneas justificadas,
estando la primera de ellas sangrada.  La anchura del sangrado se toma
del argumento @code{props}.

@example
#(define-markup-list-command (paragraph layout props args) (markup-list?)
   #:properties ((par-indent 2))
   (interpret-markup-list layout props
     #@{\markuplist \justified-lines @{ \hspace #par-indent #args @} #@}))
@end example


La versión que usa solamente Scheme es más compleja:
@example
#(define-markup-list-command (paragraph layout props args) (markup-list?)
   #:properties ((par-indent 2))
   (interpret-markup-list layout props
     (make-justified-lines-markup-list (cons (make-hspace-markup par-indent)
                                             args))))
@end example

Aparte de los argumentos usuales @code{layout} y @code{props}, la
instrucción de lista de marcados @code{paragraph} toma un argumento de
lista de marcados, llamado @code{args}.  El predicado para listas de
marcados es @code{markup-list?}.

En primer lugar, la función toma el ancho del sangrado, una propiedad
llamada aquí @code{par-indent}, de la lista de propiedades
@code{props}.  Si no se encuentra la propiedad, el valor
predeterminado es @code{2}.  Después, se hace una lista de líneas
justificadas usando la instrucción incorporada de lista de marcados
@code{\justified-lines}, que está relacionada con la función
@code{make-justified-lines-markup-list}.  Se añade un espacio
horizontal al principio usando @code{\hspace} (o la función
@code{make-hspace-markup}).  Finalmente, la lista de marcados se
interpreta usando la función @code{interpret-markup-list}.

Esta nueva instrucción de lista de marcados se puede usar como sigue:

@example
\markuplist @{
  \paragraph @{
    El arte de la tipografía musical se llama  \italic @{grabado (en plancha).@}
    El término deriva del proceso tradicional de impresión de música.
    hace sólo algunas décadas, las partituras se hacían cortando y estampando
    la música en una plancha de zinc o lata en una imagen invertida.
  @}
  \override-lines #'(par-indent . 4) \paragraph @{
    La plancha se tenía que entintar, y las depresiones causadas por los cortes
    y estampados retienen la tinta.  Se formaba una imagen presionando el papel
    contra la plancha.  El estampado y cortado se hacía completamente
    a mano.
  @}
@}
@end example


@node Contextos para programadores
@section Contextos para programadores
@translationof Contexts for programmers

@menu
* Evaluación de contextos::
* Ejecutar una función sobre todos los objetos de la presentación::
@end menu

@node Evaluación de contextos
@subsection Evaluación de contextos
@translationof Context evaluation

@cindex código, llamadas durante la interpretación
@funindex \applyContext

Se pueden modificar los contextos durante la interpretación con código
de Scheme.  La sintaxis para esto es

@example
\applyContext @var{función}
@end example

@code{@var{función}} debe ser una función de Scheme que toma un único
argumento, que es el contexto al que aplicarla.  El código siguiente
imprime el número del compás actual sobre la salida estándar durante
la compilación:

@example
\applyContext
  #(lambda (x)
    (format #t "\nSe nos ha llamado en el compás número ~a.\n"
     (ly:context-property x 'currentBarNumber)))
@end example


@node Ejecutar una función sobre todos los objetos de la presentación
@subsection Ejecutar una función sobre todos los objetos de la presentación
@translationof Running a function on all layout objects

@cindex código, llamar sobre objetos de presentación
@funindex \applyOutput


La manera más versátil de realizar el ajuste fino de un objeto es
@code{\applyOutput}, que
funciona insertando un evento dentro del contexto especificado
(@rinternals{ApplyOutputEvent}).  Su sintaxis es

@example
\applyOutput @var{Contexto} @var{proc}
@end example

@noindent
donde @code{@var{proc}} es una función de Scheme que toma tres argumentos.

Al interpretarse, la función @code{@var{proc}} se llama para cada objeto de
presentación que se encuentra en el contexto @code{@var{Contexto}}
en el tiempo actual, con los siguientes argumentos:

@itemize
@item el propio objeto de presentación,
@item el contexto en que se creó el objeto de presentación, y
@item el contexto en que se procesa @code{\applyOutput}.
@end itemize


Además, la causa del objeto de presentación, es decir el objeto o
expresión musical que es responsable de haberlo creado, está en la
propiedad @code{cause} del objeto.  Por ejemplo, para la cabeza de una
nota, éste es un evento @rinternals{NoteHead}, y para un objeto
plica, éste es un objeto @rinternals{Stem}.

He aquí una función que usar para @code{\applyOutput}; borra las
cabezas de las notas que están sobre la línea central y junto a ella:

@lilypond[quote,verbatim,ragged-right]
#(define (blanker grob grob-origin context)
   (if (and (memq 'note-head-interface (ly:grob-interfaces grob))
            (< (abs (ly:grob-property grob 'staff-position)) 2))
       (set! (ly:grob-property grob 'transparent) #t)))

\relative c' {
  a'4 e8 <<\applyOutput #'Voice #blanker a c d>> b2
}
@end lilypond

Para que @var{función} se interprete en los niveles de @code{Score} o de @code{Staff}
utilice estas formas:

@example
\applyOutput #'Score #@var{función}
\applyOutput #'Staff #@var{función}
@end example


@node Funciones de callback
@section Funciones de callback
@translationof Callback functions

Las propiedades (como @code{thickness} (grosor), @code{direction}
(dirección), etc.) se pueden establecer a valores fijos con \override,
p. ej.:

@example
\override Stem.thickness = #2.0
@end example

Las propiedades pueden fijarse también a un procedimiento de Scheme,

@lilypond[fragment,verbatim,quote,relative=2]
\override Stem.thickness = #(lambda (grob)
    (if (= UP (ly:grob-property grob 'direction))
        2.0
        7.0))
c b a g b a g b
@end lilypond

@noindent
En este caso, el procedimiento se ejecuta tan pronto como el valor de
la propiedad se reclama durante el proceso de formateo.

Casi todo el motor de tipografiado está manejado por estos
@emph{callbacks}.  Entre las propiedades que usan normalmente
@emph{callbacks} están

@table @code
@item stencil
  La rutina de impresión, que construye un dibujo para el símbolo
@item X-offset
  La rutina que establece la posición horizontal
@item X-extent
  La rutina que calcula la anchura de un objeto
@end table

El procedimiento siempre toma un argumento único, que es el grob (el
objeto gráfico).

Dicho procedimiento puede acceder al valor usual de la propiedad,
llamando en primer lugar a la función que es el @q{callback} usual
para esa propiedad, y que puede verse en el manual de referencia
interna o en el archivo 'define-grobs.scm':

@example
\relative c'' @{
  \override Flag #'X-offset = #(lambda (flag)
    (let ((default (ly:flag::calc-x-offset flag)))
      (* default 4.0)))
  c4. d8 a4. g8
@}
@end example

Si se deben llamar rutinas con varios argumentos, el grob actual se
puede insertar con una cerradura de grob.  He aquí un ajuste
procedente de @code{AccidentalSuggestion},

@example
`(X-offset .
  ,(ly:make-simple-closure
    `(,+
        ,(ly:make-simple-closure
           (list ly:self-alignment-interface::centered-on-x-parent))
      ,(ly:make-simple-closure
           (list ly:self-alignment-interface::x-aligned-on-self)))))
@end example

@noindent
En este ejemplo, tanto
@code{ly:self-alignment-interface::x-aligned-on-self} como
@code{ly:self-alignment-interface::centered-on-x-parent} se llaman con
el grob como argumento.  El resultado se añade con la función
@code{+}.  Para asegurar que esta adición se ejecuta adecuadamente,
todo ello se encierra dentro de @code{ly:make-simple-closure}.

De hecho, usar un solo procedimiento como valor de una propiedad
equivale a

@example
(ly:make-simple-closure (ly:make-simple-closure (list @var{proc})))
@end example

@noindent
El @code{ly:make-simple-closure} interior aporta el grob como
argumento de @var{proc}, el exterior asegura que el resultado de la
función es lo que se devuelve, en lugar del objeto
@code{simple-closure}.

Desde dentro de un callback, el método más fácil para evaluar un
elemento de marcado es usar grob-interpret-markup.  Por ejemplo:

@example
mi-callback = #(lambda (grob)
                 (grob-interpret-markup grob (markup "fulanito")))
@end example


@node Código de Scheme en línea
@section Código de Scheme en línea
@translationof Inline Scheme code

La principal desventaja de @code{\tweak} es su inflexibilidad
sintáctica.  Por ejemplo, lo siguiente produce un error de sintaxis (o
más bien: así lo hacía en algún momento del pasado):

@example
F = \tweak font-size #-3 -\flageolet

\relative c'' @{
  c4^\F c4_\F
@}
@end example

@noindent
Usando Scheme, se puede dar un rodeo a este problema.  La ruta hacia
el resultado se da en @ref{Añadir articulaciones a las notas
(ejemplo)}, especialmente cómo usar @code{\displayMusic} como guía de
ayuda.

@example
F = #(let ((m (make-music 'ArticulationEvent
                          'articulation-type "flageolet")))
       (set! (ly:music-property m 'tweaks)
             (acons 'font-size -3
                    (ly:music-property m 'tweaks)))
       m)

\relative c'' @{
  c4^\F c4_\F
@}
@end example

@noindent
Aquí, las propiedades @code{tweaks} del objeto flageolet @code{m}
(creado con @code{make-music}) se extraen con
@code{ly:music-property}, se antepone un nuevo par clave-valor para
cambiar el tamaño de la tipografía a la lista de propiedades con la
función de Scheme @code{acons}, y finalmente el resultado se escribe
de nuevo con @code{set!}.  El último elemento del bloque @code{let} es
el valor de retorno, el propio @code{m}.


@node Trucos difíciles
@section Trucos difíciles
@translationof Difficult tweaks

Hay un cierto número de tipos de ajustes difíciles.

@itemize


@item
Un tipo de ajuste difícil es la apariencia de los objetos de
extensión, como las ligaduras de expresión y de unión.  Inicialmente,
sólo se crea uno de estos objetos, y pueden ajustarse con el mecanismo
normal.  Sin embargo, en ciertos casos los objetos extensores cruzan
los saltos de línea.  Si esto ocurre, estos objetos se clonan.  Se
crea un objeto distinto por cada sistema en que se encuentra.  Éstos
son clones del objeto original y heredan todas sus propiedades,
incluidos los @code{\override}s.

En otras palabras, un @code{\override} siempre afecta a todas las
piezas de un objeto de extensión fragmentado.  Para cambiar sólo una
parte de un extensor en el salto de línea, es necesario inmiscuirse en
el proceso de formateado.  El @emph{callback}
@code{after-line-breaking} contiene el procedimiento Scheme que se
llama después de que se han determinado los saltos de línea, y los
objetos de presentación han sido divididos sobre los distintos
sistemas.

En el ejemplo siguiente, definimos un procedimiento
@code{my-callback}.  Este procedimiento

@itemize
@item
determina si hemos sido divididos por los saltos de línea
@item
en caso afirmativo, reúne todos los objetos divididos
@item
comprueba si somos el último de los objetos divididos
@item
en caso afirmativo, establece @code{extra-offset}.
@end itemize

Este procedimiento se instala en @rinternals{Tie} (ligadura de unión),
de forma que la última parte de la ligadura dividida se traslada hacia
arriba.

@lilypond[quote,verbatim,ragged-right]
#(define (my-callback grob)
   (let* (
          ;; have we been split?
          (orig (ly:grob-original grob))

          ;; if yes, get the split pieces (our siblings)
          (siblings (if (ly:grob? orig)
                        (ly:spanner-broken-into orig)
                        '())))

     (if (and (>= (length siblings) 2)
              (eq? (car (last-pair siblings)) grob))
         (ly:grob-set-property! grob 'extra-offset '(-2 . 5)))))

\relative c'' {
  \override Tie.after-line-breaking =
  #my-callback
  c1 ~ \break
  c2 ~ c
}
@end lilypond

@noindent
Al aplicar este truco, la nueva función de callback
@code{after-line-breaking} también debe llamar a la antigua,
si existe este valor predeterminado.  Por ejemplo, si se usa con
@code{Hairpin}, se debe llamar también a
@code{ly:spanner::kill-zero-spanned-time}.


@item Algunos objetos no se pueden cambiar con @code{\override} por
razones técnicas.  Son ejemplos @code{NonMusicalPaperColumn} y
@code{PaperColumn}.  Se pueden cambiar con la función
@code{\overrideProperty} que funciona de forma similar a @code{\once
\override}, pero usa una sintaxis distinta.

@example
\overrideProperty
Score.NonMusicalPaperColumn      % Nombre del grob
  . line-break-system-details    % Nombre de la propiedad
  . next-padding                 % Nombre de la subpropiedad, opcional
  #20                            % Valor
@end example

Observe, sin embargo, que @code{\override}, aplicado a
@code{NonMusicalPaperColumn} y a @code{PaperColumn}, aún funciona
como se espera dentro de los bloques @code{\context}.

@end itemize


@node Interfaces de Scheme de LilyPond
@chapter Interfaces de Scheme de LilyPond
@translationof LilyPond Scheme interfaces

Este capítulo cubre las diversas herramientas proporcionadas por
LilyPond como ayuda a los programadores de Scheme a extraer e
introducir información de los flujos musicales.

HACER @c TODO -- figure out what goes in here and how to organize it
