@c -*- coding: utf-8; mode: texinfo; documentlanguage: es -*-
@c This file is part of extending.tely
@ignore
- Translation of GIT committish: 87a9977bbd54e3822338e290716845d8e2e304e3
+ 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.13.29"
+@c \version "2.19.2"
@node Interfaces para programadores
@chapter Interfaces para programadores
@menu
+* Bloques de código de LilyPond::
+* Funciones de Scheme::
* Funciones musicales::
+* Funciones de eventos::
* Funciones de marcado::
* Contextos para programadores::
* Funciones de callback::
* Trucos difíciles::
@end menu
-@node Funciones musicales
-@section Funciones musicales
-@translationof Music functions
+@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:
-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.
+@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
-* Sintaxis de las funciones musicales::
-* Funciones de sustitución sencillas::
-* Funciones de sustitución intermedias::
-* Matemáticas dentro de las funciones::
-* Funciones sin argumentos::
-* Funciones vacías::
+* Definición de funciones de Scheme::
+* Uso de las funciones de Scheme::
+* Funciones de Scheme vacías::
@end menu
-@node Sintaxis de las funciones musicales
-@subsection Sintaxis de las funciones musicales
-@translationof Music function syntax
+@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 una función musical es:
+La forma general de la definición de una función de Scheme es:
@example
funcion =
-#(define-music-function
+#(define-scheme-function
(parser location @var{arg1} @var{arg2} @dots{})
- (@var{type1?} @var{type2?} @dots{})
- @var{música})
+ (@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}}
-deve devolver @code{#t}.
-
-@item @code{@var{música}}
-@tab una expresión musical, opcionalmente escrita en Scheme, con
-el código de LilyPond que pudiera tener, encerrado entre llaves
-con almohadilla
-(@tie{}@w{@code{#@{@dots{}#@}}}@tie{}). Dentro de los bloques
-de código de LilyPond, use @code{$} para referenciar a los argumentos
-de la 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)}}).
-
+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}.
-También se permiten predicados de tipo definidos por el usuario.
+@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
@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
(parser location principio-final)
(pair?)
#@{
- \once \override Beam #'positions = $principio-final
+ \once \override Beam.positions = #principio-final
#@})
\relative c' @{
(parser location beg end)
(number? number?)
#{
- \once \override Beam #'positions = $(cons beg end)
+ \once \override Beam.positions = #(cons beg end)
#})
\relative c' {
}
@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
(parser location mag)
(number?)
#{
- \override Stem #'length = $(* 7.0 mag)
- \override NoteHead #'font-size =
- $(inexact->exact (* (/ 6.0 (log 2.0)) (log mag)))
+ \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
+ \revert Stem.length
+ \revert NoteHead.font-size
}
\relative c' {
(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
+ \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' {
(parser location)
()
(if (eq? #t (ly:get-option 'display-bar-numbers))
- #@{ \once \override Score.BarNumber #'break-visibility = ##f #@}
+ #@{ \once \override Score.BarNumber.break-visibility = ##f #@}
#@{#@}))
@end example
@end example
-@node Funciones vacías
-@subsection Funciones vacías
-@translationof Void functions
+@node Funciones musicales vacías
+@subsection Funciones musicales vacías
+@translationof Void music functions
-Una función musical debe devolver una expresión musical, pero a veces
-podemos necesitar una función en la que no hay música en juego (como
-la desactivación de la funcionalidad Apuntar y Pulsar). Para hacerlo,
-devolvemos una expresión musical @code{void} (vacía).
+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.
-Este es el motivo por el que la forma que se devuelve es
-@code{(make-music ...)}. Con el valor de la propiedad @code{'void}
-establecido a @code{#t}, le decimos al analizador que descarte la
-expresión musical devuelta. así, la parte importante de la función
-musical vacía es el proceso realizado por la función, no la expresión
-musical que se devuelve.
-@example
-noApuntarYPulsar =
-#(define-music-function (parser location) ()
- (ly:set-option 'point-and-click #f)
- (make-music 'SequentialMusic 'void #t))
-...
-\noApuntarYPulsar % desactivar la funcionalidad Apuntar y Pulsar.
-@end example
+@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
@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
-El macro @code{markup} construye expresiones de marcado en Scheme,
-proporcionando una sintaxis similar a la de LilyPond. Por ejemplo:
+Para ver una expresión de marcado en su forma de Scheme, utilice
+la instrucción @code{\displayScheme}:
@example
-(markup #:column (#:line (#:bold #:italic "hola" #:raise 0.4 "mundo")
- #:larger #:line ("fulano" "fulanito" "menganito")))
+\displayScheme
+\markup @{
+ \column @{
+ \line @{ \bold \italic "hola" \raise #0.4 "mundo" @}
+ \larger \line @{ fulano fulanito menganito @}
+ @}
+@}
@end example
@noindent
-equivale a:
+La compilación del código anterior envía a la consola lo
+siguiente:
+
@example
-\markup \column @{ \line @{ \bold \italic "hola" \raise #0.4 "mundo" @}
- \larger \line @{ fulano fulanito menganito @} @}
+(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.
+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 ... @}} @tab
- @code{(markup marcado1 marcado2 ... )}
+@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 @{ ... @}} @tab @code{#:center-column ( ... )}
+@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
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}).
+definiendo instrucciones de marcado nuevas (véase
+@ref{Definición de una instrucción de marcado nueva}).
@knownissues
@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}.
+@file{scm/define-markup-commands.scm}.
@node Definición de una instrucción de marcado nueva
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} ...)
- (@var{tipo-de-arg1?} @var{tipo-de-arg2?} ...)
+(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})
- ...) ]
- ..command body..)
+ @dots{}) ]
+ @dots{}command body@dots{})
@end lisp
Los argumentos son
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
-reindimiento simplemente mediante la utilización de argumentos 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
rectángulo doble alrededor de un fragmento de texto.
En primer lugar, necesitamos construir un resultado aproximado
-utilizando marcados. Una consulta a @ruser{Text markup commands} nos
-muestra que es útil la instrucción @code{\box}:
+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
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
+\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
@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."
@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. Aquí, 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.
+@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:
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))
"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 \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
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}.
+@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á
(number-pair?)
#:category graphic
#:properties ((thickness 1))
- "...documentación..."
+ "@dots{}documentación@dots{}"
(let ((th (* (ly:output-def-lookup layout 'line-thickness)
thickness))
(x (car dest))
(define-markup-command (draw-double-line layout props dest)
(number-pair?)
#:properties ((thickness 1))
- "...documentación..."
+ "@dots{}documentación@dots{}"
(let ((th (* (ly:output-def-lookup layout 'line-thickness)
thickness))
(x (car dest))
(number-pair?)
#:properties ((thickness 1)
(line-gap 0.6))
- "...documentación..."
- ...
+ "@dots{}documentación@dots{}"
+ @dots{}
@end lisp
Finalmente, se añade el código para trazar las dos líneas. Se usan
@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
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))
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 función
-@code{make-justified-lines-markup-list}, que está relacionada con la
-instrucción incorporada de lista de marcados @code{\justified-lines}.
-Se añade un espacio horizontal al principio usando la función
-@code{make-hspace-markup}. Finalmente, la lista de marcados se
+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
-\markuplines @{
+\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.
(@rinternals{ApplyOutputEvent}). Su sintaxis es
@example
-\applyOutput @var{contexto} @var{proc}
+\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}}
+presentación que se encuentra en el contexto @code{@var{Contexto}}
en el tiempo actual, con los siguientes argumentos:
@itemize
}
@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
p. ej.:
@example
-\override Stem #'thickness = #2.0
+\override Stem.thickness = #2.0
@end example
-Las propiedades pueden fijarse también a un procedimiento de scheme,
+Las propiedades pueden fijarse también a un procedimiento de Scheme,
@lilypond[fragment,verbatim,quote,relative=2]
-\override Stem #'thickness = #(lambda (grob)
+\override Stem.thickness = #(lambda (grob)
(if (= UP (ly:grob-property grob 'direction))
2.0
7.0))
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},
@translationof Inline Scheme code
La principal desventaja de @code{\tweak} es su inflexibilidad
-sintáctica. Por ejemplo, lo siguiente produce un error de sintaxis.
+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
+F = \tweak font-size #-3 -\flageolet
\relative c'' @{
c4^\F c4_\F
@end example
@noindent
-En otras palabras, @code{\tweak} no se comporta como una articulación
-en cuando a la sintaxis; concretamente, no se puede adjuntar con
-@code{^} y @code{_}.
-
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
(ly:grob-set-property! grob 'extra-offset '(-2 . 5)))))
\relative c'' {
- \override Tie #'after-line-breaking =
+ \override Tie.after-line-breaking =
#my-callback
c1 ~ \break
- c2 ~ c
+ c2 ~ 2
}
@end lilypond
@example
\overrideProperty
-#"Score.NonMusicalPaperColumn" % Nombre del grob
-#'line-break-system-details % Nombre de la propiedad
-#'((next-padding . 20)) % Valor
+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