@c -*- coding: utf-8; mode: texinfo; documentlanguage: es -*-
@c This file is part of extending.tely
@ignore
- Translation of GIT committish: 5b7a2524c1d3b7e3df53219aafc10bb3f33a7c53
+ Translation of GIT committish: 708aa920d682cf9aa3ed647cd129afd8509760f4
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.14.0"
+@c \version "2.19.24"
@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}.
+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
* 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
+@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
-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. Mientras se está leyendo el
-bloque de código de LilyPond, se analiza sintácticamente de forma
-superficial y se sustituye por una llamada al analizador sintáctico de
-LilyPond, que funciona en tiempo de ejecución para que interprete el
-bloque de código de LilyPond.
-
-El objeto del análisis superficial es la interpretación de los
-símbolos @code{$} que se pueden usar para aislar expresiones del
-contexto léxico de Scheme que les rodea (como variables de @code{let}
-y parámetros de función). El @code{$} se puede usar de las maneras
-siguientes:
-@table @code
-@item $$
-simplemente pasa un único símbolo @code{$} al analizador de LilyPond.
-@item $@var{forma}
-evalúa la forma Scheme en tiempo de ejecución y la analiza como un
-identificador @code{\forma} en el analizador de LilyPond. Dependiendo
-del tipo del valor, se puede interpretar como varias entidades
-sintácticas diferentes.
-@item #$@var{forma}
-evalúa la forma de Scheme en tiempo de ejecución y analiza su valor
-como una expresión de Scheme dentro del analizador de LilyPond.
-@item #@var{forma}
-las formas que están dentro de expresiones de Scheme y que comienzan
-por @code{#} se leen y se analizan recursivamente hasta que se
-encuentran símbolos de @code{$}. Entonces se tratan como sigue:
-@item #@dots{}$@var{variable}
-analiza el valor de la variable dentro de la expresión circundante.
-@item #@dots{}($ @var{forma} @dots{})
-analiza el valor de la forma dentro de la expresión circundante. Al
-contrario que las @code{$@var{formas}} a nivel de LilyPond,
-necesitamos separar la forma con un espacio en blanco, haciendo que
-@code{$} sea reconocible como un símbolo de Scheme separado.
-@end table
+He aquí un ejemplo trivial:
+
+@lilypond[verbatim,quote]
+ritpp = #(define-event-function () ()
+ #{ ^"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{#}.
+
+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{\}.
+
+Toda la música generada dentro del bloque de código tiene su
+@samp{origin} establecido a la localización actual del puntero de
+entrada.
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.
+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.
+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::
@example
funcion =
#(define-scheme-function
- (parser location @var{arg1} @var{arg2} @dots{})
- (@var{type1?} @var{type2?} @dots{})
+ (@var{arg1} @var{arg2} @dots{})
+ (@var{tipo1?} @var{tipo2?} @dots{})
@var{cuerpo})
@end example
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{@var{argN}}
-@tab @var{n}-ésimo argumento
+@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}. Algunos de estos predicados se reconocen de
-forma especial por parte del analizador, véase más abajo. También
-existe una forma especial @code{(@emph{predicate?} @emph{default})}
-para especificar argumentos opcionales. Si el argumento actual no
-está presente cuando se llama 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}.
+@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} a la ubicación actual del
+cursor de entrada.
@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
+ú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 del dólar @code{$} para hacer referencia a
-argumentos de función (p.ej. @samp{$arg1}) o para iniciar una
+@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)}}). Si la función devuelve una
-expresión musical, se clona y se le da el @code{origin} correcto.
+(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
-Ciertos predicados de tipo se reconocen de forma especial por parte
-del analizador sintáctico y hacen que éste busque los argumentos
-respectivos en la sintaxis de LilyPond en lugar de hacerlo en la
-sintaxis de Scheme. Actualmente son @code{ly:music?}, @code{markup?},
-@code{ly:pitch?} y @code{ly:duration?}.
-
-Si realmente quiere escribir uno de los elementos especiales como
-Scheme en lugar de como una expresión de LilyPond, puede escribirlos
-como una expresión de Scheme que llame a @code{ly:export} en su nivel
-exterior.
-
-Otros predicados de tipo, entre ellos los que están definidos por el
-usuario hacen que el argumento respectivo sólo se acepte como una
-expresión de Scheme, normalmente precedida de @code{#} o como
-resultado de llamar a una función de Scheme.
-
-Para ver una lista de los predicados de tipo disponibles, consulte
-@ruser{Predicados de tipo predefinidos}.
+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.
+
+LilyPond resuelve algunas 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
+siguen inmediatamente, cambian dicha interpretación. 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
@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. El último argumento no puede ser un
-argumento opcional. Si hay varios argumentos opcionales seguidos, se
-rellenan con valores de izquierda a derecha. Desde el momento en que
-un argumento opcional no corresponde con la entrada, éste y todos los
-argumentos opcionales inmediatamente siguientes se sustituyen por sus
-valores predeterminados, y la correspondencia continúa con el
-siguiente argumento no opcional.
+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.
-
-Hay ciertos lugares especiales en los que un argumento que corresponde
-a @code{ly:music?} tiene que ser un identificador musical o bien una
-expresión musical encerrada dentro de @code{@{}@dots{}@code{@}} o
-@code{<<}@dots{}@code{>>} de forma explícita, de manera que las
-duraciones o post-eventos opcionales que posiblemente le sigan no
-puedan confundirse con argumentos adicionales. Un sitio obvio es
-antes de un predicado @code{ly:duration?}. Otro es el último
-argumento de una función de Scheme cuando se utiliza en un lugar en
-que tales partes opcionales podrían, o no, considerarse como parte del
-argumento musical.
-
-En esos casos raros, tenemos que delimitar nuestros argumentos
-musicales de forma adecuada para evitar la confusión por parte de
-LilyPond.
+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.
+
+Por conveniencia, las funciones de Scheme también se pueden
+llamar directamente desde Scheme, puenteando al analizador
+sintáctico de LilyPond. Su nombre puede utilizarse como el
+nombre de una función corriente. La comprobación de tipo de los
+argumentos y el salto de los argumentos opcionales tiene lugar de
+la misma forma que cuando se llama desde dentro de LilyPond,
+tomando el valor de Scheme @code{*unspecified*} el papel de la
+palabra reservada @code{\default} para saltar explícitamente
+argumentos opcionales.
@node Funciones de Scheme vacías
@subsection Funciones de Scheme vacías
@translationof Void scheme functions
-
-A veces, una función se ejecuta solamente por sus efectos colaterales.
-En tal caso, la utilización de una función de Scheme supone que su
-valor no será considerado de la forma usual:
+@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-scheme-function
- (parser location)
+#(define-void-function
+ ()
()
(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.
+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::
@example
funcion =
#(define-music-function
- (parser location @var{arg1} @var{arg2} @dots{})
+ (@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
+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}.
+Para ver una lista de los predicados de tipo disponibles,
+consulte @ruser{Predicados de tipo predefinidos}.
@seealso
@subsection Uso de las funciones musicales
@translationof Music function usage
-Las funciones musicales se pueden actualmente utilizar en tres
-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.
+Una @q{función musical} debe devolver una expresión que se
+corresponda con el predicado @code{ly:music?}. Esto hace que las
+llamadas a funciones musicales sean aproopiadas como argumentos
+del tipo @code{ly:music?} para otra llamada a una función
+musical.
+
+Si se usa una llamada a función musical dentro de otros
+contextos, el contexto puede aplicar restricciones semánticas
+adicionales.
@itemize
@item
-En el nivel superior dentro de una expresión musical. No existen
-especiales restricciones sobre la lista de argumentos.
+En el nivel superior dentro de una expresión musical no se acepta
+ningún post-evento.
@item
-Como un post-evento, que comienza explícitamente con un indicador de
-dirección (a elegir entre @code{-}, @code{^} @w{y @code{_}}). Todos
-los argumentos añadidos al final de la función musical con el
-predicado @code{ly:music?} se analizan sintácticamente también como
-post-eventos (si el último argumento es una función de Scheme, éste
-contendrá en su lugar los argumentos @code{ly:music?} del final de la
-función de Scheme). Observe que se puede aceptar la devolución de un
-post-evento por parte de las funciones musicales que se llaman como
-música normal, lo que lleva a un resultado aproximadamente equivalente
-a
-@example
-s 1*0-\fun
-@end example
+Cuando una función musical (a diferencia de una función de
+evento) devuelve una expresión del tipo post-event, LilyPond
+requiere uno de los indicadores de dirección con nombre
+(@code{-}, @code{^}, @w{y @code{_}}) para poder integrar
+adecuadamente el post-evento producido por la llamada a la
+función musical dentro de la expresión circundante.
@item
-Como componente de un acordes. Todos los argumentos añadidos al final
-de la función musical con el predicado @code{ly:music?} se analizarán
-sintácticamente también como componentes de acorde.
+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.
+Se pueden aplicar funciones @q{polimórficas}, como @code{\tweak},
+a los post-eventos, componentes de acordes y expresiones
+musicales del nivel superior.
@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.
+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}.
@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.
+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).
+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?}:
+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)
+ (principio-final)
(pair?)
#@{
- \once \override Beam #'positions = $principio-final
+ \once \override Beam.positions = #principio-final
#@})
\relative c' @{
@}
@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:
+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)
+ (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 valor
+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 (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
@lilypond[quote,verbatim,ragged-right]
AltOn =
#(define-music-function
- (parser location mag)
+ (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' {
- c2 \AltOn #0.5 c4 c
+\relative {
+ c'2 \AltOn #0.5 c4 c
\AltOn #1.5 c c \AltOff c2
}
@end lilypond
@lilypond[quote,verbatim,ragged-right]
withAlt =
#(define-music-function
- (parser location mag music)
+ (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' {
- c2 \withAlt #0.5 { c4 c }
+\relative {
+ c'2 \withAlt #0.5 { c4 c }
\withAlt #1.5 { c c } c2
}
@end lilypond
@subsection Funciones sin argumentos
@translationof Functions without arguments
-En casi todos los casos, una función sin argumentos se debe escribir
-con una variable:
+En casi todos los casos, una función sin argumentos se debe
+escribir con una variable:
@example
dolce = \markup@{ \italic \bold dolce @}
@example
mostrarNumeroDeCompas =
#(define-music-function
- (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
-Para la impresión real de los números de compás donde se llama a esta
-función, invoque a @command{lilypond} con
+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
@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,
-podría ser más sensato usar en su lugar una función de Scheme. 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.
+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
@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,raggedright]
-dyn=#(define-event-function (parser location arg) (markup?)
-(make-dynamic-script arg)) \relative c' { c\dyn pfsss }
+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 (arg) (markup?)
+ (make-dynamic-script arg))
+\relative { 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}}.
+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.
+Los elementos de marcado están implementados como funciones de
+Scheme especiales que producen un objeto @code{Stencil} dada una
+serie de argumentos.
@menu
@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}:
-El macro @code{markup} construye expresiones de marcado en Scheme,
-proporcionando una sintaxis similar a la de LilyPond. Por ejemplo:
+@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
-(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. 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.
+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 ... @}} @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
@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}).
+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
@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:
+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)))
@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}.
+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
@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.
+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} ...)
- (@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
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.
+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
@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.
+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.
+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
(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 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.
@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.
+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}:
+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:
+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:
+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.
+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 @}#@}))
+ \override #'(box-padding . 0.6) \box @{ #text @}#@}))
@end lisp
-or, equivalently
+o, de forma equivalente,
@lisp
#(define-markup-command (double-box layout props text) (markup?)
@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.
+@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:
\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:
+Sería bueno 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?)
(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 @} #@}))
+ #@{\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:
+De nuevo, la versión equivalente que utiliza la macro de marcado
+sería:
@lisp
#(define-markup-command (double-box layout props text) (markup?)
#: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.
+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.
+@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:
+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?)
(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
@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
+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
+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
(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))
(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.
+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))
- "...documentación..."
+ "@dots{}documentación@dots{}"
(let ((th (* (ly:output-def-lookup layout 'line-thickness)
thickness))
(x (car 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:
+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))
- "...documentación..."
- ...
+ "@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}:
+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)
@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}.
+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
- #@{\markuplines \justified-lines @{ \hspace #$par-indent $args @} #@}))
+ #@{\markuplist \justified-lines @{ \hspace #par-indent #args @} #@}))
@end example
@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:
+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
-\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.
@cindex código, llamadas durante la interpretación
@funindex \applyContext
+@funindex make-apply-context
+@funindex ly:context-property
+@funindex ly:context-set-property!
+@funindex ly:context-grob-definition
+@funindex ly:assoc-get
+@funindex ly:context-pushpop-property
-Se pueden modificar los contextos durante la interpretación con código
-de Scheme. La sintaxis para esto es
+Se pueden modificar los contextos durante la interpretación con
+código de Scheme. Dentro de un bloque de código de LilyPond, 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:
+En código de Scheme, la sintaxis es:
@example
-\applyContext
- #(lambda (x)
- (format #t "\nSe nos ha llamado en el compás número ~a.\n"
- (ly:context-property x 'currentBarNumber)))
+(make-apply-context @var{function})
@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. La función
+puede acceder a, así como sobreescribir u establecer propiedades
+de grobs s y propiedades de contextos. Cualquier acción tomada
+por la función que dependa del estado del contexto, está limitada
+al estado del contexto @emph{en el momento de llamar a la
+función}. Asimismo, los cambios efectuados por una llamada a
+@code{\applyContext} permanecen en efecto hasta que se modifican
+de nuevo directamente, o se revierten, incluso si han cambiado las
+condiciones iniciales sobre las que dependen.
+
+Las siguientes funciones de Scheme son útiles cuando se utiliza
+@code{\applyContext}:
+
+@table @code
+@item ly:context-property
+recuperar el valor de una propiedad de contexto
+
+@item ly:context-set-property!
+establecer el valor de una propiedad de contexto
+
+@item ly:context-grob-definition
+@itemx ly:assoc-get
+recuperar el valor de una propiedad de un grob
+
+@item ly:context-pushpop-property
+hacer una sobreescritura temporal
+(@code{\temporary@tie{}\override}) o una reversión
+(@code{\revert}) sobre una propiedad de un grob
+@end table
+
+El ejemplo siguiente recupera el valor actual de @code{fontSize},
+y a continuación lo dobla:
+
+@lilypond[quote,verbatim]
+doubleFontSize =
+\applyContext
+ #(lambda (context)
+ (let ((fontSize (ly:context-property context 'fontSize)))
+ (ly:context-set-property! context 'fontSize (+ fontSize 6))))
+
+{
+ \set fontSize = -3
+ b'4
+ \doubleFontSize
+ b'
+}
+@end lilypond
+
+
+El ejemplo siguiente recupera los colores actuales de los grobs
+@code{NoteHead}, @code{Stem} y @code{Beam}, y a continuación los
+modifica para que tengan un matiz menos saturado.
+
+@lilypond[quote,verbatim]
+desaturate =
+\applyContext
+ #(lambda (context)
+ (define (desaturate-grob grob)
+ (let* ((grob-def (ly:context-grob-definition context grob))
+ (color (ly:assoc-get 'color grob-def black))
+ (new-color (map (lambda (x) (min 1 (/ (1+ x) 2))) color)))
+ (ly:context-pushpop-property context grob 'color new-color)))
+ (for-each desaturate-grob '(NoteHead Stem Beam)))
+
+\relative {
+ \time 3/4
+ g'8[ g] \desaturate g[ g] \desaturate g[ g]
+ \override NoteHead.color = #darkred
+ \override Stem.color = #darkred
+ \override Beam.color = #darkred
+ g[ g] \desaturate g[ g] \desaturate g[ g]
+}
+@end lilypond
+
+
+Esto puede implementarse también como una función musical, con el
+objeto de restringir las modificaciones a un único bloque de
+música. Observe cómo se usa @code{ly:context-pushpop-property}
+tanto como una sobreescritura temporal
+(@code{\temporary@tie{}\override}) como una reversión
+(@code{\revert}):
+
+@lilypond[quote,verbatim]
+desaturate =
+#(define-music-function
+ (music) (ly:music?)
+ #{
+ \applyContext
+ #(lambda (context)
+ (define (desaturate-grob grob)
+ (let* ((grob-def (ly:context-grob-definition context grob))
+ (color (ly:assoc-get 'color grob-def black))
+ (new-color (map (lambda (x) (min 1 (/ (1+ x) 2))) color)))
+ (ly:context-pushpop-property context grob 'color new-color)))
+ (for-each desaturate-grob '(NoteHead Stem Beam)))
+ #music
+ \applyContext
+ #(lambda (context)
+ (define (revert-color grob)
+ (ly:context-pushpop-property context grob 'color))
+ (for-each revert-color '(NoteHead Stem Beam)))
+ #})
+
+\relative {
+ \override NoteHead.color = #darkblue
+ \override Stem.color = #darkblue
+ \override Beam.color = #darkblue
+ g'8 a b c
+ \desaturate { d c b a }
+ g b d b g2
+}
+@end lilypond
+
@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
@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
+@code{\applyOutput}, que funciona insertando un evento dentro del
+contexto especificado (@rinternals{ApplyOutputEvent}). Su
+sintaxis es o bien
@example
-\applyOutput @var{contexto} @var{proc}
+\applyOutput @var{Contexto} @var{proc}
+@end example
+
+o bien
+
+@example
+\applyOutput @var{Context}.@var{Grob} @var{proc}
@end example
@noindent
-donde @code{@var{proc}} es una función de Scheme que toma tres argumentos.
+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}}
+Al interpretarse, la función @code{@var{proc}} se llama para cada
+objeto de presentación (con el nombre del grob @var{Grob} si se
+especifica) que se encuentra en el contexto @code{@var{Contexto}}
en el tiempo actual, con los siguientes argumentos:
@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}.
+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:
+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))
+ (if (< (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
+\relative {
+ a'4 e8 <<\applyOutput Voice.NoteHead #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@dots{}
+\applyOutput Staff@dots{}
+@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.:
+(dirección), etc.) se pueden establecer a valores fijos con
+\override, 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)
+@lilypond[fragment,verbatim,quote]
+\override Stem.thickness = #(lambda (grob)
(if (= UP (ly:grob-property grob 'direction))
2.0
7.0))
-c b a g b a g b
+\relative { 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.
+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
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).
+El procedimiento siempre toma un argumento único, que es el grob
+(el objeto gráfico).
-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},
+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
-`(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})))
+\relative @{
+ \override Flag.X-offset = #(lambda (flag)
+ (let ((default (ly:flag::calc-x-offset flag)))
+ (* default 4.0)))
+ c''4. d8 a4. g8
+@}
@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:
(grob-interpret-markup grob (markup "fulanito")))
@end example
+@ignore
+
+@n ode Código de Scheme en línea
+@s ection Código de Scheme en línea
+@t ranslationof Inline Scheme code
+
+TODO: after this section had been written, LilyPond has improved
+to the point that finding a @emph{simple} example where one would
+@emph{have} to revert to Scheme has become rather hard.
-@node Código de Scheme en línea
-@section Código de Scheme en línea
-@translationof Inline Scheme code
+Until this section gets a rewrite, let's pretend we don't know.
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
+\relative @{
+ c''4^\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:music-property m 'tweaks)))
m)
-\relative c'' @{
- c4^\F c4_\F
+\relative @{
+ c''4^\F c4_\F
@}
@end example
de nuevo con @code{set!}. El último elemento del bloque @code{let} es
el valor de retorno, el propio @code{m}.
+@end ignore
+
@node Trucos difíciles
@section Trucos difíciles
@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.
+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}
+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
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.
+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)
(eq? (car (last-pair siblings)) grob))
(ly:grob-set-property! grob 'extra-offset '(-2 . 5)))))
-\relative c'' {
- \override Tie #'after-line-breaking =
+\relative {
+ \override Tie.after-line-breaking =
#my-callback
- c1 ~ \break
- c2 ~ c
+ c''1 ~ \break
+ c2 ~ 2
}
@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{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.
+@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 . 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