write .dep file.
+2004-02-09 Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+ * scripts/lilypond-book.py (Lilypond_snippet.notice_include):
+ write .dep file.
+
+2004-02-08 Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+ * Documentation/user/refman.itely (Markup command definition): Doc
+ by Nicolas Sceaux. Rewrite by Han-Wen
+
+ * lily/lyric-hyphen.cc (brew_molecule): remove if hyphen is first
+ thing of the line.
+ (brew_molecule): only remove if hyphen is not at the end of line.
+ (set_spacing_rods): new function: minimum-length specifies
+ distance between syllables.
+
+ * scm/define-grobs.scm (all-grob-descriptions): add
+ Hyphen_spanner::set_spacing_rods to LyricHyphen
+
+ * input/regression/lyric-hyphen-break.ly: new file.
+
+ * input/test/lyric-hyphen-retain.ly: new file.
+
+ * lily/new-part-combine-iterator.cc (construct_children):
+ add Rest direction.
+
+2004-02-08 Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+ * scripts/lilypond-book.py (Snippet.replacement_text): add method.
+
+ * Documentation/bibliography/engraving.bib (donemus1982):
+ update entry.
+
2004-02-07 Jan Nieuwenhuizen <janneke@gnu.org>
* scripts/lilypond.py (option_definitions): Fix typo.
note={Heussenstamm writes: Limited in scope, similar to \cite{Roemer84}}
}
-@Book {donemes1900,
- year = {1900},
+@Book {donemus1982,
+ year = {1982},
title = {Uitgeven van muziek},
author = {Donemus},
publisher= {Donemus Amsterdam},
+
+ note = {Manual on copying for composers and copyists at the Dutch
+ publishing house Donemus. Besides general comments on copying, it
+ also contains a lot of hands-on advice for making performance
+ material for modern pieces.}
+
}
@node Chord name chart
@section Chord name chart
-@lilypondfile[notexidoc]{chord-names-jazz.ly}
+@lilypondfile{chord-names-jazz.ly}
@node MIDI instruments
@section MIDI instruments
In the following example, we see how we start out with a note head
engraver.
-@lilypond[notexidoc]
+@lilypond[]
\include "engraver-example.lyinc"
\score { \topVoice
Then a @code{Staff_symbol_engraver} adds the staff:
-@lilypond[notexidoc]
+@lilypond[]
\include "engraver-example.lyinc"
\score { \topVoice
The @code{Clef_engraver} defines a reference point for the staff:
-@lilypond[notexidoc]
+@lilypond[]
\include "engraver-example.lyinc"
\score { \topVoice
And the @code{Stem_engraver} adds stems:
-@lilypond[notexidoc]
+@lilypond[]
\include "engraver-example.lyinc"
\score { \topVoice
time signature, and key signature, we get a complete piece of
notation.
-@lilypond[notexidoc]
+@lilypond[]
\include "engraver-example.lyinc"
\score { \topVoice }
This system works well for monophonic music, but what about
polyphony? In polyphonic notation, many voices can share a staff.
-@lilypond[notexidoc]
+@lilypond[]
\include "engraver-example.lyinc"
\score { \context Staff << \topVoice \\ \botVoice >> }
@end lilypond
context. In polyphonic notation, many voices can share a staff:
Similarly, more Staff contexts can be put into a single Score context.
-@lilypond[notexidoc]
+@lilypond[]
\include "engraver-example.lyinc"
\score {
<< \new Staff << \topVoice \\ \botVoice >>
by adding a dash and the character signifying the
articulation. They are demonstrated here:
-@lilypondfile[notexidoc]{script-abbreviations.ly}
+@lilypondfile[]{script-abbreviations.ly}
The meanings of these shorthands can be changed: see
@file{ly/script-init.ly} for examples.
@cindex coda
@cindex varcoda
-@lilypondfile[notexidoc]{script-chart.ly}
+@lilypondfile[]{script-chart.ly}
@refcommands
Internals: @internalsref{LyricEvent}, @internalsref{HyphenEvent}, and
@internalsref{ExtenderEvent}.
+Examples: @inputfileref{input/test,lyric-hyphen-retain.ly}
+
@refbugs
The definition of lyrics mode is too complex.
A complete example of a SATB score setup is in the file
@inputfileref{input/template,satb.ly}.
+
@refcommands
@code{\melisma}, @code{\melismaEnd}
whose source is available as
@inputfileref{input/test,bar-number-regular-interval.ly}:
-@lilypondfile[notexidoc]{bar-number-regular-interval.ly}
+@lilypondfile[]{bar-number-regular-interval.ly}
@seealso
@end example
would yield
-@lilypondfile[notexidoc]{tag-filter.ly}
+@lilypondfile[]{tag-filter.ly}
The argument of the @code{\tag} command should be a symbol, or a list
of symbols, for example,
Therefore, @code{gregorian-init.ly} also defines @code{\virgula} and
@code{\caesura}:
-@lilypondfile[notexidoc]{divisiones.ly}
+@lilypondfile[]{divisiones.ly}
@refcommands
@inputfileref{input/regression,cluster.ly}) shows what the result
looks like:
-@lilypondfile[notexidoc]{cluster.ly}
+@lilypondfile[]{cluster.ly}
By default, @internalsref{Cluster_spanner_engraver} is in the
@internalsref{Voice} context. This allows putting ordinary notes and
* Applyoutput::
* Font selection::
* Text markup::
+* Common text markup commands::
@end menu
@cindex font size, texts
+
+
+
+
+@node Common text markup commands
+@subsection Common text markup commands
+
+
The following size commands set absolute sizes:
@cindex @code{\teeny}
\notes { a^\allegro b c d }
@end verbatim
-The markup mechanism is extensible. Refer to
-@file{scm/new-markup.scm} for more information.
-
Some objects have alignment procedures of their own, which cancel out
any effects of alignments applied to their markup arguments as a
Init files: @file{scm/new-markup.scm}.
+
@refbugs
@cindex kerning
for formatting.
+@menu
+* Markup construction in scheme::
+* Markup command definition::
+@end menu
+
+@node Markup construction in scheme
+@subsubsection Markup construction in scheme
+
+@cindex defining markup commands
+
+The @code{markup} macro builds markup expressions in Scheme while
+providing a LilyPond-like syntax. For example,
+@example
+(markup #:column (#:line (#:bold #:italic "hello" #:raise 0.4 "world")
+ #:bigger #:line ("foo" "bar" "baz")))
+@end example
+
+@noindent
+is equivalent to:
+@example
+\markup \column < @{ \bold \italic "hello" \raise #0.4 "world" @}
+ \bigger @{ foo bar baz @} >
+@end example
+
+@noindent
+This example exposes the main translation rules between regular
+LilyPond markup syntax and scheme markup syntax, which are summed up
+is this table:
+@multitable @columnfractions .5 .5
+@item @b{LilyPond} @tab @b{Scheme}
+@item @code{\command} @tab @code{#:command}
+@item @code{\variable} @tab @code{variable}
+@item @code{@{ ... @}} @tab @code{#:line ( ... )}
+@item @code{\center < ... >} @tab @code{#:center ( ... )}
+@item @code{string} @tab @code{"string"}
+@item @code{#scheme-arg} @tab @code{scheme-arg}
+@end multitable
+
+Besides, the whole scheme language is accessible inside the
+@code{markup} macro: thus, one may use function calls inside
+@code{markup} in order to manipulate character strings for
+instance. This proves useful when defining new markup commands (see
+@ref{Markup command definition}).
+
+@refbugs
+
+One can not feed the @code{#:line} (resp @code{#:center},
+@code{#:column}) command with a variable or the result of a function
+call. Eg:
+@lisp
+(markup #:line (fun-that-returns-markups))
+@end lisp
+is illegal. One should use the @code{make-line-markup} (resp
+@code{make-center-markup}, @code{make-column-markup}) function
+instead:
+@lisp
+(markup (make-line-markup (fun-that-returns-markups)))
+@end lisp
+
+@node Markup command definition
+@subsubsection Markup command definition
+
+New markup commands can be defined thanks to the @code{def-markup-command} scheme macro.
+@lisp
+(def-markup-command (@emph{command-name} @emph{paper} @emph{props} @emph{arg1} @emph{arg2} ...) (@emph{arg1-type?} @emph{arg2-type?} ...)
+ ..command body..)
+
+ @emph{argi}: i@emph{th} command argument
+ @emph{argi-type?}: a type predicate for the i@emph{th} argument
+ @emph{paper}: the `paper' definition
+ @emph{props}: a list of alists, containing all active properties.
+@end lisp
+
+As a simple example, we show how to add a @code{\smallcaps} command,
+which selects @TeX{}'s small caps font. Normally, we could select the
+small caps font as follows:
+
+@verbatim
+ \markup { \override #'(font-shape . caps) Text-in-caps }
+@end verbatim
+
+This selects the caps font by setting the @code{font-shape} property to
+@code{#'caps} for interpreting @code{Text-in-caps}.
+
+To make the above available as @code{\smallcaps} command, we have to
+define a function using @code{def-markup-command}. The command should
+take a single argument, of markup type. Therefore, the start of the
+definition should read
+@example
+ (def-markup-command (smallcaps paper props argument) (markup?)
+@end example
+
+@noindent
+
+What follows is the content of the command: we should interpret
+the @code{argument} as a markup, i.e.
+
+@example
+ (interpret-markup paper @dots{} argument)
+@end example
+
+@noindent
+This interpretation should add @code{'(font-shape . caps)} to the active
+properties, so we substitute the the following for the @dots{} in the
+above example:
+
+@example
+ (cons (list '(font-shape . caps) ) props)
+@end example
+
+@noindent
+The variable @code{props} is a list of alists, and we prepend to it by
+consing a list with the extra setting.
+
+However, suppose that we are using a font that does not have a
+small-caps variant. In that case, we have to fake the small caps font,
+by setting a string in upcase, with the first letter a little larger.
+
+The @code{smallcaps} command first splits its string argument into
+tokens separated by spaces (@code{(string-split str #\Space)}); for
+each token, a markup is built with the first letter made large and
+upcased (@code{#:large (string-upcase (substring s 0 1))}), and a
+second markup built with the following letters made tiny and upcased
+(@code{#:tiny (string-upcase (substring s 1))}). As LilyPond
+introduces a space between markups on a line, the second markup is
+translated to the left (@code{#:translate (cons -0.6 0) ...}). Then,
+the markups built for each token are put in a line
+(@code{(make-line-markup ...)}). Finally, the resulting markup is
+passed to the @code{interpret-markup} function, with the @code{paper}
+and @code{props} arguments.
+
+@example
+#(def-markup-command (smallcaps paper props str) (string?)
+ "Print the string argument in small caps. Syntax: \\smallcaps #\"string\""
+ (interpret-markup paper props
+ (make-line-markup
+ (map (lambda (s)
+ (if (= (string-length s) 0)
+ s
+ (markup #:large (string-upcase (substring s 0 1))
+ #:translate (cons -0.6 0)
+ #:tiny (string-upcase (substring s 1)))))
+ (string-split str #\Space)))))
+@end example
+
+Finally, suppose that we are typesetting a recitative in an opera, and
+we would like to define a command that will show character names in a
+custom manner. Names should be printed with small caps and translated a
+bit to the left and top. We will define a @code{\character} command
+that takes into account the needed translation, and uses the newly
+defined @code{\smallcaps} command:
+
+@verbatim
+#(def-markup-command (character paper props name) (string?)
+ "Print the character name in small caps, translated to the left and
+ top. Syntax: \\character #\"name\""
+ (interpret-markup paper props
+ (markup "" #:translate (cons -4 2) #:smallcaps name)))
+@end verbatim
+
+There is one complication that needs explanation: texts above and below
+the staff are moved vertically to be at a certain distance (the
+@code{padding} property) from the staff and the notes. To make sure
+that this mechanism does not annihilate the vertical effect of our
+@code{#:translate}, we add an empty string (@code{""}) before the
+translated text. Now the @code{""} will be put above the notes, and the
+@code{name} is moved in relation to that empty string. The net effect is
+that the text is moved to the upper left.
+The final result is as follows:
+@verbatim
+\score {
+ \notes { \fatText
+ c''^\markup \character #"Cleopatra"
+ e'^\markup \character #"Giulio Cesare"
+ }
+}
+@end verbatim
+
+@lilypond[raggedright]
+#(def-markup-command (smallcaps paper props str) (string?)
+ "Print the string argument in small caps. Syntax: \\smallcaps #\"string\""
+ (interpret-markup paper props
+ (make-line-markup
+ (map (lambda (s)
+ (if (= (string-length s) 0)
+ s
+ (markup #:large (string-upcase (substring s 0 1))
+ #:translate (cons -0.6 0)
+ #:tiny (string-upcase (substring s 1)))))
+ (string-split str #\Space)))))
+
+#(def-markup-command (character paper props name) (string?)
+ "Print the character name in small caps, translated to the left and
+ top. Syntax: \\character #\"name\""
+ (interpret-markup paper props
+ (markup "" #:translate (cons -4 0) #:smallcaps name)))
+
+\score {
+ \notes { \fatText
+ c''^\markup \character #"Cleopatra"
+ e'^\markup \character #"Giulio Cesare"
+ }
+}
+@end lilypond
PACKAGE_NAME=LilyPond
MAJOR_VERSION=2
MINOR_VERSION=1
-PATCH_LEVEL=19
-MY_PATCH_LEVEL=hwn1
+PATCH_LEVEL=20
+MY_PATCH_LEVEL=
--- /dev/null
+
+
+\header {
+
+ texidoc = "Hyphens only print at the beginning of the line, when
+they go past the first note. "
+
+ }
+
+\score {
+<< \notes \new Staff \relative c'' { \time 1/4 c16[ c c c]
+\time 1/4
+c16[ c c c]
+\time 1/4
+r c16[ c c]
+
+}
+ \lyrics \new LyricsVoice {
+ bla16 -- bla -- bla -- bla --
+ bla -- bla -- bla -- bla8 --
+ bla16 -- bla -- bla
+ }>>
+ \paper {
+ indent = 0.0 \cm
+ linewidth = 3.4 \cm
+
+ \translator {
+ \StaffContext \remove "Time_signature_engraver"
+ }
+
+ }
+
+}
+
+
--- /dev/null
+
+
+\header {
+
+texidoc = "In tight situations, hyphens are removed, except at the
+end of the line. Normally, lyrics aren't set this tight, but by
+tuning down @code{padding} of in @code{SeparationItem}, syllables are put closer together, and hyphens may disappear.
+
+In some languages (eg. German and Hungarian). hyphens should not
+disappear, since spelling depends on hyphenation. In this case,
+hyphens can be forced to remain by setting @code{minimum-length} on
+the LyricHyphen grob.
+"
+
+}
+
+\score {
+<< \notes \new Staff \relative c'' { \time 1/4 c16[ c c c]
+\time 1/4
+c16[ c c c]
+\time 1/4
+c16[ c c c]
+
+}
+ \lyrics \new LyricsVoice \with {
+ % Otherwise lyrics are so far apart that hyphens don't disappear
+ SeparationItem \set #'padding = #0.0
+ }{ bla -- bla -- bla -- bla --
+ bla -- bla -- bla -- bla --
+
+ \property LyricsVoice . LyricHyphen \set #'minimum-length = #0.7
+ \property LyricsVoice . LyricHyphen \set #'spacing-procedure =
+ #Hyphen_spanner::set_spacing_rods
+
+ bla -- bla -- bla -- bla
+ }>>
+ \paper {
+ indent = 0.0 \cm
+ linewidth = 3.4 \cm
+
+ \translator {
+ \StaffContext \remove "Time_signature_engraver"
+ }
+
+ }
+
+}
+
+
*/
#if 0 // experimental code to collapse spacing after ligature
SCM incr_scm = lc->get_grob_property ("forced-spacing");
- if (incr_scm != SCM_EOL) /* (Paper_column::musical_b (l)) */
+ if (incr_scm != SCM_EOL) /* (Paper_column::is_musical (l)) */
{
me->warning (_f ("gotcha: ptr=%ul", lc));//debug
ly_display_scm (lc->self_scm ());
*/
#include "warn.hh"
-#include "hyphen-spanner.hh"
#include "item.hh"
#include "engraver.hh"
+#include "spanner.hh"
class Hyphen_engraver : public Engraver
{
+++ /dev/null
-/*
- hyphen-spanner.cc -- implement Hyphen_spanner
-
- source file of the GNU LilyPond music typesetter
-
- (c) 1999--2004 Glen Prideaux <glenprideaux@iname.com>
-
- (adapted from lyric-extender)
-*/
-
-#include <math.h>
-
-#include "box.hh"
-#include "lookup.hh"
-#include "molecule.hh"
-#include "paper-def.hh"
-#include "hyphen-spanner.hh"
-#include "paper-column.hh"
-#include "spanner.hh"
-#include "item.hh"
-
-
-MAKE_SCHEME_CALLBACK (Hyphen_spanner,brew_molecule,1)
-SCM
-Hyphen_spanner::brew_molecule (SCM smob)
-{
- Spanner * sp = unsmob_spanner (smob);
- Drul_array<Item*> bounds (sp->get_bound (LEFT),
- sp->get_bound (RIGHT));
-
- Grob * common = bounds[LEFT]->common_refpoint (bounds[RIGHT], X_AXIS);
-
- Interval span_points;
- Direction d = LEFT;
- do
- {
- Interval iv = bounds[d]->extent (common, X_AXIS);
-
- span_points[d] = iv.is_empty ()
- ? bounds[d]->relative_coordinate (common, X_AXIS)
- : iv[-d];
- }
- while (flip (&d) != LEFT);
-
- Real lt = sp->get_paper ()->get_realvar (ly_symbol2scm ("linethickness"));
- Real th = robust_scm2double (sp->get_grob_property ("thickness"), 1) * lt ;
- Real h = robust_scm2double (sp->get_grob_property ("height"), 0.5);
-
- // interval?
-
- Real dp = robust_scm2double (sp->get_grob_property ("dash-period"), 1.0);
- Real dl = robust_scm2double (sp->get_grob_property ("length"), .5 );
-
- if (dp < dl)
- dp = 1.5 * dl;
-
- Real l = span_points.length ();
- int n = int (ceil (l/dp - 0.5));
- if (n <= 0)
- n = 1;
-
- Real space_left = l - dl - (n-1)* dp;
-
- /*
- If there is not enough space, the hyphen should disappear.
- */
- if (space_left < 0)
- return SCM_EOL;
-
- Box b (Interval (0, dl), Interval (h,h+th));
- Molecule dash_mol (Lookup::round_filled_box (b, 0.8 * lt));
-
- Molecule total;
- for (int i = 0; i < n; i++)
- {
- Molecule m (dash_mol);
- m.translate_axis (span_points[LEFT] + i * dp + space_left / 2, X_AXIS);
- total.add_molecule (m);
- }
-
- total.translate_axis ( -sp->relative_coordinate (common, X_AXIS), X_AXIS);
- return total.smobbed_copy ();
-}
-
-
-ADD_INTERFACE (Hyphen_spanner, "lyric-hyphen-interface",
- "A centred hyphen is a simple line between lyrics used to divide syllables",
- "thickness height dash-period length");
-
-
+++ /dev/null
-/*
- hyphen-spanner.hh -- part of GNU LilyPond
-
- (c) 1999--2004 Glen Prideaux <glenprideaux@iname.com>
-*/
-
-#ifndef HYPHEN_SPANNER_HH
-#define HYPHEN_SPANNER_HH
-
-#include "spanner.hh"
-
-struct Hyphen_spanner
-{
-public:
- DECLARE_SCHEME_CALLBACK(set_spacing_rods, (SCM));
- void set_textitem (Direction, Grob*);
- bool has_interface (Grob*);
- DECLARE_SCHEME_CALLBACK (brew_molecule, (SCM ));
-};
-
-#endif // HYPHEN_SPANNER_HH
-
--- /dev/null
+/*
+ hyphen-spanner.hh -- part of GNU LilyPond
+
+ (c) 1999--2004 Glen Prideaux <glenprideaux@iname.com>
+*/
+
+#ifndef HYPHEN_SPANNER_HH
+#define HYPHEN_SPANNER_HH
+
+#include "spanner.hh"
+
+struct Hyphen_spanner
+{
+public:
+ DECLARE_SCHEME_CALLBACK(set_spacing_rods, (SCM));
+ bool has_interface (Grob*);
+ DECLARE_SCHEME_CALLBACK (brew_molecule, (SCM ));
+};
+
+#endif // HYPHEN_SPANNER_HH
+
*/
-#ifndef P_COL_HH
-#define P_COL_HH
+#ifndef PAPER_COLUMN_HH
+#define PAPER_COLUMN_HH
#include "item.hh"
#include "rod.hh"
DECLARE_SCHEME_CALLBACK(before_line_breaking, (SCM));
Paper_column (SCM);
- static bool musical_b (Grob *);
+ static bool is_musical (Grob *);
static Moment when_mom (Grob*);
- static bool used_b (Grob*) ;
+ static bool is_used (Grob*) ;
void set_rank (int);
};
-#endif // P_COL_HH
+#endif // PAPER_COLUMN_HH
--- /dev/null
+/*
+ hyphen-spanner.cc -- implement Hyphen_spanner
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 2003--2004 Han-Wen Nienhuys <hanwen@xs4all.nl>
+*/
+
+#include <math.h>
+
+#include "box.hh"
+#include "lookup.hh"
+#include "molecule.hh"
+#include "paper-def.hh"
+#include "paper-column.hh"
+#include "spanner.hh"
+#include "item.hh"
+#include "lyric-hyphen.hh"
+#include "moment.hh"
+
+MAKE_SCHEME_CALLBACK (Hyphen_spanner,brew_molecule,1)
+SCM
+Hyphen_spanner::brew_molecule (SCM smob)
+{
+ Spanner * me = unsmob_spanner (smob);
+ Drul_array<Item*> bounds (me->get_bound (LEFT),
+ me->get_bound (RIGHT));
+
+ if (bounds[LEFT]->break_status_dir ()
+ && Paper_column::when_mom (bounds[LEFT]) == Paper_column::when_mom (bounds[RIGHT]->get_column()))
+ return SCM_EOL;
+
+ Grob * common = bounds[LEFT]->common_refpoint (bounds[RIGHT], X_AXIS);
+
+ Interval span_points;
+ Direction d = LEFT;
+ do
+ {
+ Interval iv = bounds[d]->extent (common, X_AXIS);
+
+ span_points[d] = iv.is_empty ()
+ ? bounds[d]->relative_coordinate (common, X_AXIS)
+ : iv[-d];
+ }
+ while (flip (&d) != LEFT);
+
+ Real lt = me->get_paper ()->get_realvar (ly_symbol2scm ("linethickness"));
+ Real th = robust_scm2double (me->get_grob_property ("thickness"), 1) * lt ;
+ Real h = robust_scm2double (me->get_grob_property ("height"), 0.5);
+
+ // interval?
+
+ Real dp = robust_scm2double (me->get_grob_property ("dash-period"), 1.0);
+ Real dl = robust_scm2double (me->get_grob_property ("length"), .5 );
+
+ if (dp < dl)
+ dp = 1.5 * dl;
+
+ Real l = span_points.length ();
+ int n = int (ceil (l/dp - 0.5));
+ if (n <= 0)
+ n = 1;
+
+ Real space_left = l - dl - (n-1)* dp;
+
+ /*
+ If there is not enough space, the hyphen should disappear, but not
+ at the end of the line.
+ */
+ if (space_left < 0.0
+ && !bounds[RIGHT]->break_status_dir ())
+ return SCM_EOL;
+
+ space_left = space_left >? 0.0;
+
+ Box b (Interval (0, dl), Interval (h,h+th));
+ Molecule dash_mol (Lookup::round_filled_box (b, 0.8 * lt));
+
+ Molecule total;
+ for (int i = 0; i < n; i++)
+ {
+ Molecule m (dash_mol);
+ m.translate_axis (span_points[LEFT] + i * dp + space_left / 2, X_AXIS);
+ total.add_molecule (m);
+ }
+
+ total.translate_axis ( -me->relative_coordinate (common, X_AXIS), X_AXIS);
+ return total.smobbed_copy ();
+}
+
+
+MAKE_SCHEME_CALLBACK (Hyphen_spanner,set_spacing_rods,1);
+SCM
+Hyphen_spanner::set_spacing_rods (SCM smob)
+{
+ Grob*me = unsmob_grob (smob);
+
+ Rod r;
+ Spanner*sp = dynamic_cast<Spanner*> (me);
+ r.distance_ =
+ robust_scm2double (me->get_grob_property ("minimum-length"), 0);
+ Direction d=LEFT;
+ do {
+ r.item_l_drul_[d] = sp->get_bound (d);
+ r.distance_ += r.item_l_drul_[d]->extent (r.item_l_drul_[d], X_AXIS)[-d];
+ } while (flip (&d) != LEFT);
+
+ r.add_to_cols ();
+ return SCM_UNSPECIFIED;
+}
+
+ADD_INTERFACE (Hyphen_spanner, "lyric-hyphen-interface",
+ "A centred hyphen is a simple line between lyrics used to divide syllables",
+ "thickness height dash-period minimum-length length");
+
+
"DynamicLineSpanner",
"Tie",
"Dots",
+ "Rest",
"Slur",
"TextScript",
"Script",
}
bool
-Paper_column::musical_b (Grob *me)
+Paper_column::is_musical (Grob *me)
{
SCM m = me->get_grob_property ("shortest-starter-duration");
Moment s (0);
bool
-Paper_column::used_b (Grob*me)
+Paper_column::is_used (Grob*me)
{
return gh_pair_p (me->get_grob_property ("elements")) || Item::breakable_b (me)
|| gh_pair_p (me->get_grob_property ("bounded-by-me"))
seem empty. We need to retain breakable columns, in case
someone forced a breakpoint.
*/
- if (!bfound || !Paper_column::used_b (acs[i]))
+ if (!bfound || !Paper_column::is_used (acs[i]))
acs.del (i);
}
return acs;
\consists "Stanza_number_engraver"
\consists "Vocal_name_engraver"
\consists "Skip_event_swallow_translator"
- SeparationItem \set #'padding = #0.5
+ SeparationItem \set #'padding = #0.2
}
\translator {
# it is not, for --srcdir builds
$(outdir)/%.texi: %.tely
if [ -f $@ ]; then chmod a+w $@; fi
- time $(PYTHON) $(LILYPOND_BOOK) $(LILYPOND_BOOK_INCLUDES) --process='$(LILYPOND) $(LILYPOND_BOOK_INCLUDES)' --output=$(outdir) --format=$(LILYPOND_BOOK_FORMAT) --verbose $(LILYPOND_BOOK_FLAGS) $<
+ $(PYTHON) $(LILYPOND_BOOK) $(LILYPOND_BOOK_INCLUDES) --process='$(LILYPOND) $(LILYPOND_BOOK_INCLUDES)' --output=$(outdir) --format=$(LILYPOND_BOOK_FORMAT) --verbose $(LILYPOND_BOOK_FLAGS) $<
chmod -w $@
$(outdir)/%.texi: $(outdir)/%.tely
(height . 0.42)
(dash-period . 10.0)
(length . 0.66)
- (minimum-length . 0.5)
+ (spacing-procedure . ,Hyphen_spanner::set_spacing_rods)
(molecule-callback . ,Hyphen_spanner::brew_molecule)
(Y-extent-callback . ,Grob::point_dimension_callback)
(meta . ((interfaces . (lyric-interface lyric-hyphen-interface
'lilypond_block': r'''(?ms)^(?P<match>@lilypond(\[(?P<options>[^]]*)\])?\s(?P<code>.*?)@end lilypond)\s''',
'lilypond_file': '(?m)^(?P<match>@lilypondfile(\[(?P<options>[^]]*)\])?{(?P<filename>[^}]+)})',
'multiline_comment': r"(?sm)^\s*(?!@c\s+)(?P<code>@ignore\s.*?@end ignore)\s",
- 'singleline_comment': r"(?m)^.*?(?P<match>(?P<code>@c([ \t][^\n]*|)\n))",
- 'verb': r'''(?P<code>@code{.*?})''',
- 'verbatim': r'''(?s)(?P<code>@example\s.*?@end example\s)''',
+ 'singleline_comment': r"(?m)^.*(?P<match>(?P<code>@c([ \t][^\n]*|)\n))",
+
+# don't do this: fucks up with @code{@{}
+# 'verb': r'''(?P<code>@code{.*?})''',
+ 'verbatim': r'''(?s)(?P<code>@example\s.*?@end\s+example\s)''',
},
}
class Chunk:
def replacement_text (self):
return ''
-
+ def is_outdated (self):
+ return 0
class Substring (Chunk):
def __init__ (self, source, start, end):
self.end = end
def replacement_text (self):
return self.source [self.start:self.end]
- def outdated_p (self):
- return 0
class Snippet (Chunk):
def __init__ (self, type, match, format):
self.hash = 0
self.options = []
self.format = format
+ def replacement_text (self):
+ return self.match.group (0)
+
def substring (self, s):
return self.match.group (s)
def filter_code (self):
return `self.__class__` + " type = " + self.type
class Include_snippet (Snippet):
+ def processed_filename (self):
+ f = self.substring ('filename')
+ return os.path.splitext (f)[0] + format2ext[format]
+
def replacement_text (self):
s = self.match.group (0)
f = self.substring ('filename')
- nf = os.path.splitext (f)[0] + format2ext[format]
-
- return re.sub (f, nf, s)
+
+ return re.sub (f, self.processed_filename (), s)
class Lilypond_snippet (Snippet):
def __init__ (self, type, match, format):
outf = open (self.basename () + '.ly', 'w')
outf.write (self.full_ly ())
- def outdated_p (self):
+ def is_outdated (self):
base = self.basename ()
if os.path.exists (base + '.ly') \
and os.path.exists (base + '.tex') \
LATEX: '.tex',
}
+
def do_file (input_filename):
#ugh
global format
ly.progress (_ ("Dissecting..."))
snippet_types = (
'lilypond_block',
- 'verb',
+# 'verb',
'verbatim',
'singleline_comment',
'multiline_comment',
if filter_cmd:
pass # todo
elif process_cmd:
- outdated = filter (lambda x: x.__class__ == Lilypond_snippet and x.outdated_p (),
+ outdated = filter (lambda x: x.__class__ == Lilypond_snippet and x.is_outdated (),
chunks)
ly.progress (_ ("Writing snippets..."))
map (Lilypond_snippet.write_ly, outdated)
output_file.writelines ([s.replacement_text () for s in chunks])
- ## UGH. how do you do dynamic_cast/typecheck in Python?
+
+ included_files = []
+ def notice_include (target, snip):
+ included_files.append (snip.match.group ('filename'))
+ included_files.append (os.path.join (output_name, snip.processed_filename ()))
+
+ [notice_include (output_filename, x) for x in
+
+ ## UGH. how do you do dynamic_cast/typecheck in Python?
+ filter (lambda x: x.__class__ == Include_snippet, chunks)]
+
+ target = re.sub (r'^\./','', output_filename)
+ open (os.path.split (output_filename)[1] + '.dep', 'w').write ('%s: %s\n' % (target,
+ string.join (included_files)))
+
map (process_include, filter (lambda x: x.__class__ == Include_snippet, chunks))
+
def do_options ():
global format, output_name
global filter_cmd, process_cmd, verbose_p
ly.setup_environment ()
if files:
do_file (files[0])
-
if __name__ == '__main__':
main ()