section on orchestral stuff and identifiers.
* lily/spacing-spanner.cc (musical_column_spacing): use average,
not maximum of spacing wishes in polyphonic situations.
* scm/define-grobs.scm (all-grob-descriptions): bold tuplet
number
* lilypond-indent.el: remove paren matching.
* lily/text-item.cc (interpret_new_markup): new function
use iso. text2molecule.
* lily/main.cc (notice): change FSF address
* po/de.po: update PO file to 1.6.
+2003-07-15 Han-Wen Nienhuys <hanwen@cs.uu.nl>
+
+ * Documentation/user/tutorial.itely (An orchestral part): new
+ section on orchestral stuff and identifiers.
+
2003-07-14 Heikki Junes <hjunes@cc.hut.fi>
* lilypond-mode.el: comment-out paren-highlighting, it still causes
2003-07-14 Han-Wen Nienhuys <hanwen@cs.uu.nl>
+ * lily/spacing-spanner.cc (musical_column_spacing): use average,
+ not maximum of spacing wishes in polyphonic situations.
+
+ * scm/define-grobs.scm (all-grob-descriptions): bold tuplet
+ number
+
+ * lilypond-indent.el: remove paren matching.
+
+ * lily/text-item.cc (interpret_new_markup): new function
+ use iso. text2molecule.
+
* lily/main.cc (notice): change FSF address
* po/de.po: update PO file to 1.6.
can exist during parsing:
@table @code
@item Duration
-@item Identifier
@item Input
@item Moment
@item Music
+@item Event
+In C++ terms, an @code{Event} is a subtype of @code{Music}. However,
+both have different functions in the syntax.
@item Music_output_def
@item Pitch
@item Score
@item Spring_smob
-@item Translator: An object that produces audio objects or Grobs. This is
-not yet user-accessible.
+@item Translator: An object that produces audio objects or Grobs.
+It may be accessed with @code{\applyoutput}.
@item Font_metric: An object representing a font.
@end table
* Vocal music::
* Tablatures::
* Chord names::
-* Writing parts::
+* Orchestral music::
* Ancient notation ::
* Contemporary notation::
* Tuning output::
* Relative octaves::
* Bar check::
* Skipping corrected music::
-* Automatic note splitting::
+* Automatic note splitting ::
@end menu
@node Key signature
@subsection Key signature
-@cindex Key
+@cindex Key signature
@cindex @code{\key}
@section Expressive marks
@menu
-* Slurs::
+* Slurs ::
* Phrasing slurs::
* Breath marks::
* Metronome marks::
-@node Writing parts
-@section Writing parts
+@node Orchestral music
+@section Orchestral music
+
+@cindex Writing parts
Orchestral music involves some special notation, both in the full
score and the individual parts. This section explains how to tackle
@menu
+* Multiple staff contexts::
* Rehearsal marks::
* Bar numbers::
* Instrument names::
* Sound output for transposing instruments::
@end menu
+@node Multiple staff contexts
+@subsection Multiple staff contexts
+
+Polyphonic scores consist of many staffs. These staffs can be
+constructed in three different ways:
+@itemize @bullet
+@item The group is started with a brace at the left. This is done with the
+@internalsref{GrandStaff} context.
+@item The group is started with a bracket. This is done with the
+@internalsref{StaffGroup} context
+@item The group is started with a vertical line. This is the default
+for the score.
+@end itemize
+
+@cindex Staff, multiple
+@cindex bracket, vertical
+@cindex brace, vertical
+@cindex grand staff
+@cindex staff group
+
+
+
@node Rehearsal marks
@subsection Rehearsal marks
object, and set a object property in that object.
@menu
-* Tuning objects::
+* Tuning objects ::
* Constructing a tweak::
* Applyoutput::
* Outputproperty::
* Printing lyrics::
* A lead sheet::
* Listening to output::
-* Titling::
-* Single staff polyphony::
+* Titling ::
+* Single staff polyphony ::
* Piano staffs::
* Setting variables::
* Fine tuning layout::
Clefs are fully explained in @ref{Clef}.
-When you enter these commands in a file, you must to enclose them in
-@code{\notes @{@dots{}@}}. This lets LilyPond know that music (as
-opposed to @rglos{lyrics}) follows:
+These commands must be enclosed in @code{\notes @{@dots{}@}}. This
+indicates that music (as opposed to @rglos{lyrics}) follows:
@example
\notes @{
@end quotation
@separate
+@menu
+* Combining music into compound expressions::
+* Adding articulation marks to notes ::
+* More basic rhythms::
+* Commenting input files::
+@end menu
+
+@node Combining music into compound expressions
+@subsection Combining music into compound expressions
+
To print more than one staff, each piece of music that makes up a staff
is marked by adding @code{\context Staff} before it. These
@code{Staff}'s are then grouped inside @code{\simultaneous @{} and @code{@}}, as is
@end lilypond
@end quotation
-The time signature is specified in one melody staff only
-(the top staff), but is printed on both, since common practice
-dictates that all staves have the same time signature.
+The example shows how small chunks of music, for example the notes
+@code{c2}, @code{e4}, etc. of the second staff, are combined to form a
+larger chunk by enclosing it in braces. Again, a larger chunk is
+formed by prefix @code{\context Staff} to it, and that chunk is
+combined with @code{< >}. This mechanism is similar with mathematical
+formulas: in a formula, a so-called expression is formed by combining
+simpler expressions into larger expressions. For example,
-@separate
+@quotation
+ 1
+
+ 1 + 2
+
+ (1 + 2) * 3
+
+ ((1 + 2) * 3) / (4 * 5)
+@end quotation
+is a sequence of expressions, where each expression is contained in
+the next one. The simplest expressions are numbers and operators
+(like +, * and /). Parentheses are used to group expressions. In
+LilyPond input, a similar mechanism is used. Here, the simplest
+expressions are notes and rests. By enclosing expressions in @code{<
+>} and @code{@{ @}}, more complex music is formed. The @code{\context}
+also forms new expressions; it is prepended to a music expression.
+
+When spreading expressions over multiple lines, it is customary to use
+an indent that indicates the nesting level. Formatting music like this
+eases reading, and helps you insert the right amount of closing
+braces at the end of an expression. For example
+@example
+\score @{
+ \notes <
+ @{
+ @dots{}
+ @}
+ @{
+ @dots{}
+ @}
+ >
+@}
+@end example
+
+@node Adding articulation marks to notes
+@subsection Adding articulation marks to notes
Common accents can be added to a note using @code{-.}, @code{--}, @code{->}:
@quotation
@end lilypond
-
-
-
Dynamic signs are made by adding the markings to the note:
@quotation
@lilypond[verbatim,relative 1]
@separate
+@node More basic rhythms
+@subsection More basic rhythms
+
A pickup (or upstep) is entered with the keyword @code{\partial}. It
is followed by a duration: @code{\partial 4} is a quarter note upstep
and @code{\partial 8} an eighth note.
More information on the use of grace notes is in @ref{Grace notes}.
+@node Commenting input files
+@subsection Commenting input files
+
Comments are pieces of the input that are ignored. There are two
types of comments. A line comments are introduced by @code{%}: after
that, the rest of that line is ignored. Block comments span larger
< @{ a4 g2 f4-~ f4 @} \\
@{ r4 g4 f2 f4 @} >
@end example
-@lilypond[relative=2]
+@lilypond[relative 1]
\context Staff < { a4 g2 f4-~ f4 } \\
{ r4 g4 f2 f4 } >
@end lilypond
< @{ a4 g2 f4-~ f4 @} \\
@{ s4 g4 f2 f4 @} >
@end example
-@lilypond[relative=2]
+@lilypond[relative 1]
\context Staff < { a4 g2 f4-~ f4 } \\
{ s4 g4 f2 f4 } >
@end lilypond
@cindex setting object properties
-@lilypond[relative 2,verbatim]
+@lilypond[relative 1,verbatim]
\stemUp
f-5
\once \property Voice.Fingering
@node Organizing larger pieces
@section Organizing larger pieces
-TODO: discuss identifiers, include files, \version.
+When all of the elements discussed earlier are combined to produce
+larger files, the @code{\score} blocks get a lot bigger, because the
+music expressions are longer, and, in the case of polyphonic and/or
+orchestral pieces, more deeply nested.
+
+By using variables, also known as identifiers, it is possible to break
+up complex music expressions.
+An identifier is assigned as follows
+@example
+ namedMusic = \notes @{ @dots{}
+@end example
+
+The contents of the music expression @code{namedMusic}, can be used
+later by preceding the name with a backslash, i.e. @code{\namedMusic}.
+For example
+
+@lilypond[singleline,verbatim]
+seufzer = \notes {
+ dis'8 e'8
+}
+\score { \notes {
+ \seufzer \seufzer
+} }
+@end lilypond
+
+The name of an identifier should only have alphabetic characters only,
+and no numbers, underscores or dashes. The assignment should be
+outside of the @code{\score} block.
+It is possible to use variables for many other types of objects in the
+input. For example,
+@example
+ width = 1.5\cm
+ name = "Wendy"
+ aFivePaper = \paper @{ paperheight = 22.7 \cm @}
+@end example
+Depending on its contents, the identifier can be used in different
+places. The following example uses the above variables:
+@example
+ \score @{
+ \notes @{ c4^\name @}
+ \paper @{
+ \aFivePaper
+ linewidth = \width
+ @}
+ @}
+@end example
+
+More information on the possible uses of identifiers is in the
+technical manual, in @ref{Scheme datatypes}.
@node An orchestral part
@section An orchestral part
-TODO:
+In orchestral music, all notes are printed twice: both in a part for
+the musicians, and in a full score for the which is printed both in
+parts as in full score. Identifiers can be used to avoid double work:
+the music is entered once, and stored in an variables. The contents of
+that variable is then used to generate both the part and the score.
-\markup, mmrest, transposing, cue notes
+It is convenient to define the notes in a special file, for example,
+suppose that the following is in @file{horn-music.ly}:
+@example
+hornNotes = \notes \relative c @{
+ \time 2/4
+ r4 f8 a cis4 f e d
+@}
+@end example
+Then, an individual part is made by putting the following in a file
+@example
+\include "horn-music.ly"
+\header @{
+ instrument = "Horn in F"
+@}
+\score @{
+ \notes \transpose c' f \hornNotes
+@}
+@end example
+The @code{\include} command substitutes the contents of the file at
+this position in the file, so that @code{hornNotes} is defined
+afterwards. Since the horn is tuned in F, the @code{\transpose}
+command is used. The code @code{\transpose c' f} indicates that the
+argument, being @code{\hornNotes} should be transposed by a fifth
+downwards: the @code{c'} becomes a @code{f}. The transposition can be
+seen in the following output:
+
+@lilypond[singleline]
+\score {
+ \notes \transpose c' f \notes \relative c' {
+ \time 2/4
+ r4 f8 a cis4 f e d
+}
+}
+@end lilypond
+In ensemble pieces, one of the voices often does not play for many
+measures. This is denoted by a special rest, the multi-measure
+rest. It is entered with a capital R, and followed by a duration (1
+for a whole note, 2 for a half note, etc.) By multiplying the
+duration, longer rests can be constructed. For example, the next rest
+takes 3 measures in 2/4 time.
+@example
+ R2*3
+@end example
+
+When printing the part, the following @code{skipBars} property must be
+set to false, to prevent the rest from being expanded in three one bar
+rests.
+@example
+ \property Score.skipBars = ##t
+@end example
+
+The result would look like
+
+@lilypond[singleline]
+\score {\notes { \transpose c' f \relative c' { \time 2/4
+\property Score.skipBars = ##t
+ R2*3
+ r4 f8 a cis4 f e d } }}
+@end lilypond
+
+The score is made by combining all of the music in a @code{\score}
+block, assuming that the other voice is in @code{hornNotes}, in the
+file @file{horn-music.ly}:
+@example
+\include "fagot-music.ly"
+\include "horn-music.ly"
+
+\score @{
+ \simultaneous @{
+ \context Staff = hornStaff \hornNotes
+ \context Staff = fagStaff \fagottoNotes
+ @} @}
+@end example
+
+This would lead to the following output:
+
+@lilypond[singleline]
+\score {
+ \notes \relative c \simultaneous {
+ \context Staff = hornStaff { \time 2/4
+ R2*3
+ r4 f8 a cis4 f e d }
+ \context Staff = fagStaff { \clef bass
+ r4 d,8 f | gis4 c | b bes |
+ a8 e f4 | g d | gis f }
+ } }
+@end lilypond
+
+More in depth information is in the notation manual, in
+@ref{Orchestral music}.
-@separate
-@example
-\version "1.5.72"
-@end example
-Lilypond and its language are still under development, and
-occasionally details of the syntax are changed. The @code{version}
-fragment indicates which LilyPond version the input file was written
-for. When you compile this file, the version number will be
-checked. When the file is too old, a warning is issued. The version
-number is also used by the @code{convert-ly} program (See
-@ref{Invoking convert-ly}), which updates the file to the latest
-version automatically.
@node Integrating text and music
@section Integrating text and music
+TODO: shorten.
@cindex La@TeX{}, music in
@cindex HTML, music in
c'2^"Tutti" g
c, r
R1*1
- r8 [g' g g] g-[ g e c]
+ r8 g' g g g g e c
g'4 g, r2
R1*18
r2 r4^"Solo" g'4 |
a4 ( c8-) f4 ( b,8-)
d4. ( c8-) r r
R2.*3|
- r4 r8 r4 c'8
+ r4 r8 r4 c8
b4( c8-) b4( c8-)
bes4. ~ bes4 g8
a4 c8 f-[ ( d-) b!]
\mark "E"
R2.*9 |
\lipbreaker
- c8-[ c' c] c4.~
- c8-[ c d] e-[ e fis]
+ c8-[ c' c] c4.~
+ c8-[ c d] e-[ e fis]
g4 r8 r4 r8
R2.
r8 g,-[ g] g-[ g g] |
c4 r8 r4 r8 \bar "|."
}
-
-
-
-
\score
{
\notes { \transpose c' bes \rondo }
SCM properties = Font_interface::font_alist_chain (me);
-
- Molecule tm = Text_item::text2molecule (me, scm_makfrom0str (str.to_str0 ()), properties);
+ Molecule tm = Text_item::interpret_new_markup
+ (me->self_scm(), properties, scm_makfrom0str (str.to_str0 ()));
the_beam.add_at_edge (Y_AXIS, UP, tm, 5.0, 0);
}
#endif
* stafflinethickness) rather than hardwired to (staff_space / 6).
*/
+/*
+ WTF: what does Breathing_sign have to do with text?!
+
+ --hwn
+ */
MAKE_SCHEME_CALLBACK (Breathing_sign,brew_molecule,1);
SCM
Breathing_sign::brew_molecule (SCM smob)
if (text == SCM_EOL)
return divisio_minima (smob);
SCM properties = Font_interface::font_alist_chain (me);
- Molecule out;
- out = Text_item::text2molecule (me, text, properties);
+ Molecule out = Text_item::interpret_new_markup (smob, properties, text);
SCM space_scm = me->get_grob_property ("word-space");
if (gh_number_p (space_scm))
{
static Molecule string2molecule (Grob *me, SCM text, SCM properties);
static Molecule markup_text2molecule (Grob *me, SCM markup_text, SCM properties);
static bool has_interface (Grob*);
-
+ static Molecule interpret_new_markup (SCM grob, SCM achain, SCM markup);
private:
static Molecule lookup_character (Grob *me, Font_metric*, SCM char_name);
static Molecule lookup_text (Grob *me, Font_metric*, SCM text);
String r = to_string (Paper_column::get_rank (me));
SCM properties = Font_interface::font_alist_chain (me);
- Molecule t = Text_item::text2molecule (me, scm_makfrom0str (r.to_str0 ()),
- properties);
+ Molecule t = Text_item::interpret_new_markup (p, properties,
+ scm_makfrom0str (r.to_str0 ()));
t.align_to (X_AXIS, CENTER);
t.align_to (Y_AXIS, DOWN);
%token <scm> DURATION_IDENTIFIER
%token <scm> FRACTION
%token <id> IDENTIFIER
-%token <scm> CHORDNAMES CHORDNAMES_IDENTIFIER
+%token <scm> CHORDNAMES
%token <scm> CHORD_MODIFIER
bool expand_only = false;
Real base_note_space = note_spacing (me, lc, rc, shortest, &expand_only);
- Real max_note_space = -infinity_f;
- Real max_fixed_note_space = -infinity_f;
-
+ Real compound_note_space = 0.0;
+ Real compound_fixed_note_space = 0.0;
+ int wish_count = 0;
+
SCM seq = lc->get_grob_property ("right-neighbors");
/*
Real fixed =0.0;
Note_spacing::get_spacing (wish, rc, base_note_space, increment, &space, &fixed);
- max_note_space = max_note_space >? space;
- max_fixed_note_space = max_fixed_note_space >? fixed;
+
+
+ compound_note_space = compound_note_space + space;
+ compound_fixed_note_space = compound_fixed_note_space + fixed;
+ wish_count ++;
+
}
}
/*
Ugh. 0.8 is arbitrary.
*/
- max_note_space *= 0.8;
+ compound_note_space *= 0.8;
}
- if (max_note_space < 0)
+ if (compound_note_space < 0 || wish_count == 0)
+ {
+ compound_note_space = base_note_space;
+ compound_fixed_note_space = increment;
+ }
+ else
{
- max_note_space = base_note_space;
- max_fixed_note_space = increment;
+ compound_note_space /= wish_count;
+ compound_fixed_note_space /= wish_count;
}
/*
TODO: this criterion is discontinuous in the derivative.
Maybe it should be continuous?
*/
- max_fixed_note_space = max_fixed_note_space <? max_note_space;
+ compound_fixed_note_space = compound_fixed_note_space <? compound_note_space;
bool packed = to_boolean (me->get_paper ()->get_scmvar ("packed"));
Real strength, distance;
line will then be stretched to fill the whole linewidth.
*/
strength = 1.0;
- distance = max_fixed_note_space;
+ distance = compound_fixed_note_space;
}
else
{
- strength = 1 / (max_note_space - max_fixed_note_space);
- distance = max_note_space;
+ strength = 1 / (compound_note_space - compound_fixed_note_space);
+ distance = compound_note_space;
}
// Spaceable_grob::add_spring (lc, rc, distance, strength, expand_only);
return proc;
}
+
+
+Molecule
+Text_item::interpret_new_markup (SCM grob, SCM achain,
+ SCM markup)
+{
+ static SCM proc;
+ if (!proc)
+ proc = scm_c_eval_string ("interpret-markup");
+
+ return *unsmob_molecule (scm_call_3 (proc, grob, achain, markup));
+}
/*
TODO: use markup.
*/
- edge[d] = Text_item::text2molecule (me, text, properties);
+
+ edge[d] = Text_item::interpret_new_markup (smob, properties, text);
if (!edge[d].empty_b ())
edge[d].align_to (Y_AXIS, CENTER);
}
SCM text = textbit->get_grob_property("text");
if (gh_string_p (text)) {
SCM properties = Font_interface::font_alist_chain (me);
- Molecule mol = Text_item::text2molecule (me, text, properties);
+
+ Molecule mol = Text_item::interpret_new_markup (me->self_scm (),
+ properties, text);
extra_short += mol.extent(X_AXIS).length() / 2;
}
}
me->set_grob_property ("font-family", ly_symbol2scm ("number"));
Molecule n =
- Text_item::text2molecule (me, scm_makfrom0str (to_string (num).to_str0 ()),
- chain);
+ Text_item::interpret_new_markup (me->self_scm(), chain,scm_makfrom0str (to_string (num).to_str0 ()));
+
Molecule d =
- Text_item::text2molecule (me, scm_makfrom0str (to_string (den).to_str0 ()),
- chain);
+ Text_item::interpret_new_markup (me->self_scm(), chain,scm_makfrom0str (to_string (den).to_str0 ()));
n.align_to (X_AXIS, CENTER);
d.align_to (X_AXIS, CENTER);
Molecule m;
if (gh_string_p (number) && number_visibility)
{
SCM properties = Font_interface::font_alist_chain (me);
- Molecule num = Text_item::text2molecule (me, number, properties);
+ Molecule num = Text_item::interpret_new_markup (smob, properties, number);
num.align_to (X_AXIS, CENTER);
num.translate_axis (w/2, X_AXIS);
num.align_to (Y_AXIS, CENTER);
SCM text = me->get_grob_property ("text");
SCM properties = me->get_property_alist_chain (SCM_EOL);
- Molecule num = Text_item::text2molecule (me, text, properties);
+ Molecule num = Text_item::interpret_new_markup (smob, properties, text);
mol.add_at_edge (X_AXIS, LEFT, num, - num.extent (X_AXIS).length ()
- 1.0, 0);
"This function is redefined to be used in Emacs' show-paren-function and
in XEmacs' paren-highlight."
(LilyPond-blink-matching-paren dir))
-
-;;; From Emacs' paren.el, with minimal changes (see "LilyPond"-lines)
-;; Find the place to show, if there is one,
-;; and show it until input arrives.
-(defun LilyPond-show-paren-function ()
- (if LilyPond-show-paren-mode
- (let (pos dir mismatch face (oldpos (point)))
- (cond ((eq (char-syntax (preceding-char)) ?\))
- (setq dir -1))
- ((eq (char-syntax (following-char)) ?\()
- (setq dir 1)))
- ;;
- ;; Find the other end of the sexp.
- (when (and dir
- (not (LilyPond-inside-string-or-comment-p)))
- (save-excursion
- (save-restriction
- ;; Determine the range within which to look for a match.
- (when blink-matching-paren-distance
- (narrow-to-region
- (max (point-min) (- (point) blink-matching-paren-distance))
- (min (point-max) (+ (point) blink-matching-paren-distance))))
- ;; Scan across one sexp within that range.
- ;; Errors or nil mean there is a mismatch.
- (condition-case ()
- (setq pos (LilyPond-scan-sexps (point) dir))
- (error (setq pos t mismatch t)))
- ;; If found a "matching" paren, see if it is the right
- ;; kind of paren to match the one we started at.
- (when (integerp pos)
- (let ((beg (min pos oldpos)) (end (max pos oldpos)))
- (when (/= (char-syntax (char-after beg)) ?\$)
- (setq mismatch
- (not (eq (char-before end)
- ;; This can give nil.
- (matching-paren (char-after beg)))))))))))
- ;;
- ;; Highlight the other end of the sexp, or unhighlight if none.
- (if (not pos)
- (progn
- ;; If not at a paren that has a match,
- ;; turn off any previous paren highlighting.
- (and show-paren-overlay (overlay-buffer show-paren-overlay)
- (delete-overlay show-paren-overlay))
- (and show-paren-overlay-1 (overlay-buffer show-paren-overlay-1)
- (delete-overlay show-paren-overlay-1)))
- ;;
- ;; Use the correct face.
- (if mismatch
- (progn
- (if show-paren-ring-bell-on-mismatch
- (beep))
- (setq face 'show-paren-mismatch-face))
- (setq face 'show-paren-match-face))
- ;;
- ;; If matching backwards, highlight the closeparen
- ;; before point as well as its matching open.
- ;; If matching forward, and the openparen is unbalanced,
- ;; highlight the paren at point to indicate misbalance.
- ;; Otherwise, turn off any such highlighting.
- (if (and (= dir 1) (integerp pos))
- (when (and show-paren-overlay-1
- (overlay-buffer show-paren-overlay-1))
- (delete-overlay show-paren-overlay-1))
- (let ((from (if (= dir 1)
- (point)
- (forward-point -1)))
- (to (if (= dir 1)
- (forward-point 1)
- (point))))
- (if show-paren-overlay-1
- (move-overlay show-paren-overlay-1 from to (current-buffer))
- (setq show-paren-overlay-1 (make-overlay from to)))
- ;; Always set the overlay face, since it varies.
- (overlay-put show-paren-overlay-1 'priority show-paren-priority)
- (overlay-put show-paren-overlay-1 'face face)))
- ;;
- ;; Turn on highlighting for the matching paren, if found.
- ;; If it's an unmatched paren, turn off any such highlighting.
- (unless (integerp pos)
- (delete-overlay show-paren-overlay))
- (let ((to (if (or (eq show-paren-style 'expression)
- (and (eq show-paren-style 'mixed)
- (not (pos-visible-in-window-p pos))))
- (point)
- pos))
- (from (if (or (eq show-paren-style 'expression)
- (and (eq show-paren-style 'mixed)
- (not (pos-visible-in-window-p pos))))
- pos
- (save-excursion
- (goto-char pos)
- (forward-point (- dir))))))
- (if show-paren-overlay
- (move-overlay show-paren-overlay from to (current-buffer))
- (setq show-paren-overlay (make-overlay from to))))
- ;;
- ;; Always set the overlay face, since it varies.
- (overlay-put show-paren-overlay 'priority show-paren-priority)
- (overlay-put show-paren-overlay 'face face)))
- ;; show-paren-mode is nil in this buffer.
- (and show-paren-overlay
- (delete-overlay show-paren-overlay))
- (and show-paren-overlay-1
- (delete-overlay show-paren-overlay-1))))
-
-;;; From XEmacs' paren.el, with minimal changes (see "LilyPond"-lines)
-;; Find the place to show, if there is one,
-;; and show it until input arrives.
-(defun LilyPond-paren-highlight ()
- "This highlights matching parentheses.
-
-See the variables:
- paren-message-offscreen use modeline when matching paren is offscreen?
- paren-ding-unmatched make noise when passing over mismatched parens?
- paren-mode 'blink-paren, 'paren, or 'sexp
- blink-matching-paren-distance maximum distance to search for parens.
-
-and the following faces:
- paren-match, paren-mismatch, paren-blink-off"
-
- ;; I suppose I could check here to see if a keyboard macro is executing,
- ;; but I did a quick empirical check and couldn't tell that there was any
- ;; difference in performance
-
- (let ((oldpos (point))
- (pface nil) ; face for paren...nil kills the overlay
- (dir (and paren-mode
- (not (input-pending-p))
- (not executing-kbd-macro)
- (cond ((eq (char-syntax (preceding-char)) ?\))
- -1)
- ((eq (char-syntax (following-char)) ?\()
- 1))))
- pos mismatch)
-
- (save-excursion
- (if (or (not dir)
- (LilyPond-inside-string-or-comment-p)
- (not (save-restriction
- ;; Determine the range within which to look for a match.
- (if blink-matching-paren-distance
- (narrow-to-region
- (max (point-min)
- (- (point) blink-matching-paren-distance))
- (min (point-max)
- (+ (point) blink-matching-paren-distance))))
-
- ;; Scan across one sexp within that range.
- (condition-case nil
- (setq pos (LilyPond-scan-sexps (point) dir))
- ;; NOTE - if blink-matching-paren-distance is set,
- ;; then we can have spurious unmatched parens.
- (error (paren-maybe-ding)
- nil)))))
-
- ;; do nothing if we didn't find a matching paren...
- nil
-
- ;; See if the "matching" paren is the right kind of paren
- ;; to match the one we started at.
- (let ((beg (min pos oldpos)) (end (max pos oldpos)))
- (setq mismatch
- (and (/= (char-syntax (char-after beg)) ?\\)
- (/= (char-syntax (char-after beg)) ?\$)
- ;; XEmacs change
- (matching-paren (char-after beg))
- (/= (char-after (1- end))
- (matching-paren (char-after beg)))))
- (if (eq paren-mode 'sexp)
- (setq paren-extent (make-extent beg end))))
- (and mismatch
- (paren-maybe-ding))
- (setq pface (if mismatch
- 'paren-mismatch
- 'paren-match))
- (and (memq paren-mode '(blink-paren paren))
- (setq paren-extent (make-extent (- pos dir) pos)))
-
- (if (and paren-message-offscreen
- (eq dir -1)
- (not (current-message))
- (not (window-minibuffer-p (selected-window)))
- (not (pos-visible-in-window-safe pos)))
- (paren-describe-match pos mismatch))
-
- ;; put the right face on the extent
- (cond (pface
- (set-extent-face paren-extent pface)
- (set-extent-priority paren-extent 100) ; want this to be high
- (and (eq paren-mode 'blink-paren)
- (setq paren-blink-on-face pface
- paren-n-blinks 0
- paren-timeout-id
- (and paren-blink-interval
- (add-timeout paren-blink-interval
- 'paren-blink-timeout
- nil
- paren-blink-interval))))))
- ))))
-
-(if (not (string-match "XEmacs\\|Lucid" emacs-version))
-;;; EMACS' Lilypond-show-paren-mode definition
-(define-minor-mode LilyPond-show-paren-mode
- "Toggle Show Paren mode.
-With prefix ARG, turn Show Paren mode on if and only if ARG is positive.
-Returns the new status of Show Paren mode (non-nil means on).
-
-When Show Paren mode is enabled, any matching parenthesis is highlighted
-in `show-paren-style' after `show-paren-delay' seconds of Emacs idle time."
- :global t :group 'LilyPond-paren-showing
- ;; Turn off the usual paren-matching method
- ;; when this one is turned on.
- (if (local-variable-p 'LilyPond-show-paren-mode)
- (make-local-variable 'blink-matching-paren-on-screen)
- (kill-local-variable 'blink-matching-paren-on-screen))
- (setq blink-matching-paren-on-screen (not LilyPond-show-paren-mode))
- ;; Now enable or disable the mechanism.
- ;; First get rid of the old idle timer.
- (if show-paren-idle-timer
- (cancel-timer show-paren-idle-timer))
- (if (boundp 'LilyPond-show-paren-idle-timer)
- (cancel-timer LilyPond-show-paren-idle-timer))
- (setq LilyPond-show-paren-idle-timer nil)
- ;; If show-paren-mode is enabled in some buffer now,
- ;; set up a new timer.
- (when (memq t (mapcar (lambda (buffer)
- (or (with-current-buffer buffer
- show-paren-mode)
- (with-current-buffer buffer
- LilyPond-show-paren-mode)))
- (buffer-list)))
- (setq LilyPond-show-paren-idle-timer (run-with-idle-timer
- show-paren-delay t
- 'LilyPond-show-paren-function)))
- (unless show-paren-mode
- (and show-paren-overlay
- (eq (overlay-buffer show-paren-overlay) (current-buffer))
- (delete-overlay show-paren-overlay))
- (and show-paren-overlay-1
- (eq (overlay-buffer show-paren-overlay-1) (current-buffer))
- (delete-overlay show-paren-overlay-1))))
-;;; XEMACS' Lilypond-paren-set-mode definition
-(defun LilyPond-paren-set-mode (arg &optional quiet)
- "Cycles through possible values for `paren-mode', force off with negative arg.
-When called from lisp, a symbolic value for `paren-mode' can be passed directly.
-See also `paren-mode' and `paren-highlight'."
- (interactive "P")
- ;; kill off the competition, er, uh, eliminate redundancy...
- (setq post-command-hook (delq 'show-paren-command-hook post-command-hook))
- (setq pre-command-hook (delq 'blink-paren-pre-command pre-command-hook))
- (setq post-command-hook (delq 'blink-paren-post-command post-command-hook))
-
- (let* ((paren-modes '(blink-paren paren sexp))
- (paren-next-modes (cons nil (append paren-modes (list nil)))))
- (setq paren-mode (if (and (numberp arg) (< arg 0))
- nil ; turn paren highlighting off
- (cond ((and arg (symbolp arg)) arg)
- ((and (numberp arg) (> arg 0))
- (nth (1- arg) paren-modes))
- ((numberp arg) nil)
- (t (car (cdr (memq paren-mode
- paren-next-modes)))))
- )))
- (cond (paren-mode
- (add-hook 'post-command-hook 'LilyPond-paren-highlight)
- (add-hook 'pre-command-hook 'paren-nuke-extent)
- (setq blink-matching-paren nil))
- ((not (local-variable-p 'paren-mode (current-buffer)))
- (remove-hook 'post-command-hook 'LilyPond-paren-highlight)
- (remove-hook 'pre-command-hook 'paren-nuke-extent)
- (paren-nuke-extent) ; overkill
- (setq blink-matching-paren t)
- ))
- (or quiet (message "Paren mode is %s" (or paren-mode "OFF"))))
-)
BuildRoot: %{_tmppath}/%{name}-%{version}-root
-Buildrequires: t1utils bison flex mftrace texinfo
+Buildrequires: t1utils bison flex mftrace
+Buildrequires: texinfo >= 4.6
Requires: tetex tetex-latex libstdc++ python
Requires: guile >= 1.6.4-7
%
% Functions for direct and embedded PostScript
+
/blot-diameter { lilypondpaperblotdiameter } bind def
/set_tex_dimen {
cvr def
} bind def
+
+
/euclidean_length
{
1 copy mul exch 1 copy mul add sqrt
## todo:
## have better algorithm for deciding when to crop page,
## and when to show full page
-
+ base = re.sub (r'\.e?ps', '', ps_name)
+
header = open (ps_name).read (1024)
multi_page = re.search ('\n%%Pages: ', header)
cmd = ''
cmd = r'''gs -g%dx%d -sDEVICE=pnggray -dTextAlphaBits=4 -dGraphicsAlphaBits=4 -q -sOutputFile=%s -r%d -dNOPAUSE %s %s -c quit ''' % \
(x, y, output_file, resolution, trans_ps, ps_name)
+
+ rmfile = base + '-page*.png'
else:
output_file = re.sub (r'\.e?ps', '-page%d.png', ps_name)
-
+ rmfile = base + '.png'
cmd = r'''gs -s -sDEVICE=pnggray -dTextAlphaBits=4 -dGraphicsAlphaBits=4 -q -sOutputFile=%s -dNOPAUSE -r%d %s -c quit''' % (output_file,
resolution, ps_name)
status = system (cmd)
signal = 0xf & status
exit_status = status >> 8
+
+ rms = glob.glob (rmfile)
+ print 'removing ', rms
+ map (os.unlink, rms)
if status:
os.unlink (png)
(molecule-callback . ,Tuplet_bracket::brew_molecule)
(font-family . roman)
(font-shape . italic)
+ (font-series . bold)
(font-relative-size . -1)
(meta . ((interfaces . (text-interface tuplet-bracket-interface font-interface spanner-interface))))
needed_filetypes.append ('eps')
pathbase = os.path.join (g_outdir, basename)
- def f (base, ext1, ext2):
- a = os.path.isfile (base + ext2)
- if (os.path.isfile (base + ext1) and
- os.path.isfile (base + ext2) and
- os.stat (base+ext1)[stat.ST_MTIME] >
- os.stat (base+ext2)[stat.ST_MTIME]) or \
- not os.path.isfile (base + ext2):
+ def must_rebuild (base, ext1, ext2):
+
+ f2 = base + ext2
+ f1 = base + ext1
+ fp2 = base + '-page1' + ext2
+
+ isfile2 = os.path.isfile (f2)
+
+ if not isfile2 and os.path.isfile (fp2):
+ f2 = fp2
+ isfile2 = os.path.isfile (fp2)
+
+ if (os.path.isfile (f2) and isfile2 and
+ os.stat (f1)[stat.ST_MTIME] >
+ os.stat (f2)[stat.ST_MTIME]) or \
+ not isfile2:
+
return 1
+
todo = []
- if 'tex' in needed_filetypes and f (pathbase, '.ly', '.tex'):
+ if 'tex' in needed_filetypes and must_rebuild (pathbase, '.ly', '.tex'):
todo.append ('tex')
- if 'eps' in needed_filetypes and f (pathbase, '.tex', '.eps'):
+ if 'eps' in needed_filetypes and must_rebuild (pathbase, '.tex', '.eps'):
todo.append ('eps')
- if 'png' in needed_filetypes and f (pathbase, '.eps', '.png'):
+ if 'png' in needed_filetypes and must_rebuild (pathbase, '.eps', '.png'):
todo.append ('png')
return ('lilypond', body, opts, todo, basename)